//=============================================================================
//  Overture Document Library
//
//  Copyright (C) 2010-2011 Rui Fan <vanferry@gmail.com>
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License version 2.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================

#include "ove.h"

#include <QFile>
#include <QIODevice>
#include <QMap>
#include <QPair>
#include <QTextCodec>
#include <QString>
#include <QStringList>
#include <cmath>
#include <cstdlib>

namespace OVE {

/*template <class T>
inline void deleteVector(QList<T*>& vec) {
	for (int i=0; i<vec.size(); ++i)
		delete vec[i];
	}
	//vec.clear();
}*/

NoteUtility::NoteUtility() {
}

NoteUtility::~NoteUtility() {
}

int NoteUtility::NoteTypeToTick(NoteType type, int quarter) {
	int c = int(pow(2.0, (int)type)) ;
	return quarter * 4 * 2 / c ;
}

///////////////////////////////////////////////////////////////////////////////
TickElement::TickElement() {
	tick_ = 0;
}

void TickElement::setTick(int tick) {
	tick_ = tick;
}

int TickElement::getTick(void) const {
	return tick_;
}

///////////////////////////////////////////////////////////////////////////////
MeasurePos::MeasurePos() {
	measure_ = 0;
	offset_ = 0;
}

void MeasurePos::setMeasure(int measure) {
	measure_ = measure;
}

int MeasurePos::getMeasure() const {
	return measure_;
}

void MeasurePos::setOffset(int offset) {
	offset_ = offset;
}

int MeasurePos::getOffset() const {
	return offset_;
}

MeasurePos MeasurePos::shiftMeasure(int measure) const {
	MeasurePos mp;
	mp.setMeasure(getMeasure() + measure);
	mp.setOffset(getOffset());

	return mp;
}

MeasurePos MeasurePos::shiftOffset(int offset) const {
	MeasurePos mp;
	mp.setMeasure(getMeasure());
	mp.setOffset(getOffset() + offset);

	return mp;
}

bool MeasurePos::operator ==(const MeasurePos& mp) const {
	return getMeasure() == mp.getMeasure() && getOffset() == mp.getOffset();
}

bool MeasurePos::operator !=(const MeasurePos& mp) const {
	return !(*this == mp);
}

bool MeasurePos::operator <(const MeasurePos& mp) const {
	if (getMeasure() != mp.getMeasure()) {
		return getMeasure() < mp.getMeasure();
	}

	return getOffset() < mp.getOffset();
}

bool MeasurePos::operator <=(const MeasurePos& mp) const {
	if (getMeasure() != mp.getMeasure()) {
		return getMeasure() <= mp.getMeasure();
	}

	return getOffset() <= mp.getOffset();
}

bool MeasurePos::operator >(const MeasurePos& mp) const {
	return !(*this <= mp);
}

bool MeasurePos::operator >=(const MeasurePos& mp) const {
	return !(*this < mp);
}

///////////////////////////////////////////////////////////////////////////////
PairElement::PairElement() {
	start_ = new MeasurePos();
	stop_ = new MeasurePos();
}

PairElement::~PairElement(){
	delete start_;
	delete stop_;
}

MeasurePos* PairElement::start() const {
	return start_;
}

MeasurePos* PairElement::stop() const {
	return stop_;
}

///////////////////////////////////////////////////////////////////////////////
PairEnds::PairEnds() {
	leftLine_ = new LineElement();
	rightLine_ = new LineElement();
	leftShoulder_ = new OffsetElement();
	rightShoulder_ = new OffsetElement();
}

PairEnds::~PairEnds(){
	delete leftLine_;
	delete rightLine_;
	delete leftShoulder_;
	delete rightShoulder_;
}

LineElement* PairEnds::getLeftLine() const {
	return leftLine_;
}

LineElement* PairEnds::getRightLine() const {
	return rightLine_;
}

OffsetElement* PairEnds::getLeftShoulder() const {
	return leftShoulder_;
}

OffsetElement* PairEnds::getRightShoulder() const {
	return rightShoulder_;
}

///////////////////////////////////////////////////////////////////////////////
LineElement::LineElement() {
	line_ = 0;
}

void LineElement::setLine(int line) {
	line_ = line;
}

int LineElement::getLine(void) const {
	return line_;
}

///////////////////////////////////////////////////////////////////////////////
OffsetElement::OffsetElement() {
	xOffset_ = 0;
	yOffset_ = 0;
}

void OffsetElement::setXOffset(int offset) {
	xOffset_ = offset;
}

int OffsetElement::getXOffset() const {
	return xOffset_;
}

void OffsetElement::setYOffset(int offset) {
	yOffset_ = offset;
}

int OffsetElement::getYOffset() const {
	return yOffset_;
}

///////////////////////////////////////////////////////////////////////////////
LengthElement::LengthElement() {
	length_ = 0;
}

void LengthElement::setLength(int length) {
	length_ = length;
}

int LengthElement::getLength() const {
	return length_;
}

///////////////////////////////////////////////////////////////////////////////
MusicData::MusicData() {
	musicDataType_ = MusicData_None;
	show_ = true;
	color_ = 0;
	voice_ = 0;
	xmlVoice_ = 0;
}

MusicDataType MusicData::getMusicDataType() const {
	return musicDataType_;
}

MusicData::XmlDataType MusicData::getXmlDataType(MusicDataType type) {
	XmlDataType xmlType = None;

	switch (type) {
	case MusicData_Measure_Repeat: {
		xmlType = Attributes;
		break;
	}
	case MusicData_Beam: {
		xmlType = NoteBeam;
		break;
	}
	case MusicData_Slur:
	case MusicData_Glissando:
	case MusicData_Tuplet:
	case MusicData_Tie: {
		xmlType = Notations;
		break;
	}
	case MusicData_Text:
	case MusicData_Repeat:
	case MusicData_Wedge:
	case MusicData_Dynamics:
	case MusicData_Pedal:
	case MusicData_OctaveShift_EndPoint: {
		xmlType = Direction;
		break;
	}
	default: {
		xmlType = None;
		break;
	}
	}

	return xmlType;
}

/*bool MusicData::get_is_pair_element(MusicDataType type)
 {
 bool pair = false;

 switch ( type )
 {
 case MusicData_Numeric_Ending :
 case MusicData_Measure_Repeat :
 case MusicData_Wedge :
 case MusicData_OctaveShift :
 //case MusicData_OctaveShift_EndPoint :
 case MusicData_Pedal :
 case MusicData_Beam :
 case MusicData_Glissando :
 case MusicData_Slur :
 case MusicData_Tie :
 case MusicData_Tuplet :
 {
 pair = true;
 break;
 }
 default:
 break;
 }

 return pair;
 }*/

void MusicData::setShow(bool show) {
	show_ = show;
}

bool MusicData::getShow() const {
	return show_;
}

void MusicData::setColor(unsigned int color) {
	color_ = color;
}

unsigned int MusicData::getColor() const {
	return color_;
}

void MusicData::setVoice(unsigned int voice) {
	voice_ = voice;
}

unsigned int MusicData::getVoice() const {
	return voice_;
}

void MusicData::copyCommonBlock(const MusicData& source) {
	setTick(source.getTick());
	start()->setOffset(source.start()->getOffset());
	setColor(source.getColor());
}

void MusicData::setXmlVoice(unsigned int voice) {
	xmlVoice_ = voice;
}

unsigned int MusicData::getXmlVoice() const {
	return xmlVoice_;
}

///////////////////////////////////////////////////////////////////////////////
MidiData::MidiData() {
	midiType_ = Midi_None;
}

MidiType MidiData::getMidiType() const {
	return midiType_;
}

///////////////////////////////////////////////////////////////////////////////
OveSong::OveSong() :
	codec_(0) {
	clear();
}

OveSong::~OveSong() {
	clear();
}

void OveSong::setIsVersion4(bool version4){
	version4_ = version4;
}

bool OveSong::getIsVersion4() const {
	return version4_;
}

void OveSong::setQuarter(int tick) {
	quarter_ = tick;
}

int OveSong::getQuarter(void) const {
	return quarter_;
}

void OveSong::setShowPageMargin(bool show){
	showPageMargin_ = show;
}

bool OveSong::getShowPageMargin() const {
	return showPageMargin_;
}

void OveSong::setShowTransposeTrack(bool show) {
	showTransposeTrack = show;
}

bool OveSong::getShowTransposeTrack() const {
	return showTransposeTrack;
}

void OveSong::setShowLineBreak(bool show) {
	showLineBreak_ = show;
}

bool OveSong::getShowLineBreak() const {
	return showLineBreak_;
}

void OveSong::setShowRuler(bool show) {
	showRuler_ = show;
}

bool OveSong::getShowRuler() const {
	return showRuler_;
}

void OveSong::setShowColor(bool show) {
	showColor_ = show;
}

bool OveSong::getShowColor() const {
	return showColor_;
}

void OveSong::setPlayRepeat(bool play) {
	playRepeat_ = play;
}

bool OveSong::getPlayRepeat() const {
	return playRepeat_;
}

void OveSong::setPlayStyle(PlayStyle style) {
	playStyle_ = style;
}

OveSong::PlayStyle OveSong::getPlayStyle() const {
	return playStyle_;
}

void OveSong::addTitle(const QString& str) {
	titles_.push_back(str);
}

QList<QString> OveSong::getTitles(void) const {
	return titles_;
}

void OveSong::addAnnotate(const QString& str) {
	annotates_.push_back(str);
}

QList<QString> OveSong::getAnnotates(void) const {
	return annotates_;
}

void OveSong::addWriter(const QString& str) {
	writers_.push_back(str);
}

QList<QString> OveSong::getWriters(void) const {
	return writers_;
}

void OveSong::addCopyright(const QString& str) {
	copyrights_.push_back(str);
}

QList<QString> OveSong::getCopyrights(void) const {
	return copyrights_;
}

void OveSong::addHeader(const QString& str) {
	headers_.push_back(str);
}

QList<QString> OveSong::getHeaders(void) const {
	return headers_;
}

void OveSong::addFooter(const QString& str) {
	footers_.push_back(str);
}

QList<QString> OveSong::getFooters(void) const {
	return footers_;
}

void OveSong::addTrack(Track* ptr) {
	tracks_.push_back(ptr);
}

int OveSong::getTrackCount(void) const {
	return tracks_.size();
}

QList<Track*> OveSong::getTracks() const {
	return tracks_;
}

void OveSong::setTrackBarCount(int count) {
	trackBarCount_ = count;
}

int OveSong::getTrackBarCount() const {
	return trackBarCount_;
}

Track* OveSong::getTrack(int part, int staff) const {
	int trackId = partStaffToTrack(part, staff);

	if( trackId >=0 && trackId < (int)tracks_.size() ) {
		return tracks_[trackId];
	}

	return 0;
}

bool OveSong::addPage(Page* page) {
	pages_.push_back(page);
	return true;
}

int OveSong::getPageCount() const {
	return pages_.size();
}

Page* OveSong::getPage(int idx) {
	if( idx>=0 && idx<(int)pages_.size() ) {
		return pages_[idx];
	}

	return 0;
}

void OveSong::addLine(Line* ptr) {
	lines_.push_back(ptr);
}

int OveSong::getLineCount() const {
	return lines_.size();
}

Line* OveSong::getLine(int idx) const {
	if( idx >=0 && idx<(int)lines_.size() ) {
		return lines_[idx];
	}

	return 0;
}

void OveSong::addMeasure(Measure* measure) {
	measures_.push_back(measure);
}

int OveSong::getMeasureCount(void) const {
	return measures_.size();
}

Measure* OveSong::getMeasure(int bar) const {
	if( bar >= 0 && bar < (int)measures_.size() ) {
		return measures_[bar];
	}

	return 0;
}

void OveSong::addMeasureData(MeasureData* measureData) {
	measureDatas_.push_back(measureData);
}

int OveSong::getMeasureDataCount(void) const {
	return measureDatas_.size();
}

MeasureData* OveSong::getMeasureData(int part, int staff/*=0*/, int bar) const {
	int trackId = partStaffToTrack(part, staff);
	int trackBarCount = getTrackBarCount();

	if( bar >= 0 && bar < trackBarCount ) {
		int measureId = trackBarCount * trackId + bar;

		if( measureId >=0 && measureId < (int)measureDatas_.size() ) {
			return measureDatas_[measureId];
		}
	}

	return 0;
}

MeasureData* OveSong::getMeasureData(int track, int bar) const {
	int id = trackBarCount_*track + bar;

	if( id >=0 && id < (int)measureDatas_.size() ) {
		return measureDatas_[id];
	}

	return 0;
}

void OveSong::setPartStaffCounts(const QList<int>& partStaffCounts) {
	//partStaffCounts_.assign(partStaffCounts.begin(), partStaffCounts.end());
	for(int i=0; i<partStaffCounts.size(); ++i) {
		partStaffCounts_.push_back(partStaffCounts[i]);
	}
}

int OveSong::getPartCount() const {
	return partStaffCounts_.size();
}

int OveSong::getStaffCount(int part) const {
	if( part>=0 && part<(int)partStaffCounts_.size() ) {
		return partStaffCounts_[part];
	}

	return 0;
}

int OveSong::getPartBarCount() const {
	return measureDatas_.size() / tracks_.size();
}

QPair<int, int> OveSong::trackToPartStaff(int track) const {
	QPair<int, int> partStaff;
	int i;
	int staffCount = 0;

	for( i=0; i<partStaffCounts_.size(); ++i ) {
		if( staffCount + partStaffCounts_[i] > track ) {
			return qMakePair((int)i, track-staffCount);
		}

		staffCount += partStaffCounts_[i];
	}

	return qMakePair((int)partStaffCounts_.size(), 0);
}

int OveSong::partStaffToTrack(int part, int staff) const {
	int i;
	unsigned int staffCount = 0;

	for( i=0; i<partStaffCounts_.size(); ++i ) {
		if( part == (int)i && staff>=0 && staff<(int)partStaffCounts_[i] ) {
			int trackId = staffCount + staff;

			if( trackId >=0 && trackId < (int)tracks_.size() ) {
				return trackId;
			}
		}

		staffCount += partStaffCounts_[i];
	}

	return tracks_.size();
}

void OveSong::setTextCodecName(const QString& codecName) {
	codec_ = QTextCodec::codecForName(codecName.toLatin1());
}

QString OveSong::getCodecString(const QByteArray& text) {
    QString s;
    if (codec_ == NULL)
        s = QString(text);
    else
        s = codec_->toUnicode(text);

    s = s.trimmed();
    return s;
}

void OveSong::clear(void) {
	version4_ = true;
	quarter_ = 480;
	showPageMargin_ = false;
	showTransposeTrack = false;
	showLineBreak_ = false;
	showRuler_ = false;
	showColor_ = true;
	playRepeat_ = true;
	playStyle_ = Record;

	annotates_.clear();
	copyrights_.clear();
	footers_.clear();
	headers_.clear();
	titles_.clear();
	writers_.clear();

//	deleteVector(tracks_);
	for(int i=0; i<tracks_.size(); ++i){
		delete tracks_[i];
	}
	for(int i=0; i<pages_.size(); ++i){
		delete pages_[i];
	}
	for(int i=0; i<lines_.size(); ++i){
		delete lines_[i];
	}
	for(int i=0; i<measures_.size(); ++i){
		delete measures_[i];
	}
	for(int i=0; i<measureDatas_.size(); ++i){
		delete measureDatas_[i];
	}
	tracks_.clear();
	pages_.clear();
	lines_.clear();
	measures_.clear();
	measureDatas_.clear();
	trackBarCount_ = 0;
	partStaffCounts_.clear();
}

///////////////////////////////////////////////////////////////////////////////
Voice::Voice() {
	channel_ = 0;
	volume_ = -1;
	pitchShift_ = 0;
	pan_ = 0;
	patch_ = 0;
	stemType_ = 0;
}

void Voice::setChannel(int channel) {
	channel_ = channel;
}

int Voice::getChannel() const {
	return channel_;
}

void Voice::setVolume(int volume) {
	volume_ = volume;
}

int Voice::getVolume() const {
	return volume_;
}

void Voice::setPitchShift(int pitchShift) {
	pitchShift_ = pitchShift;
}

int Voice::getPitchShift() const {
	return pitchShift_;
}

void Voice::setPan(int pan) {
	pan_ = pan;
}

int Voice::getPan() const {
	return pan_;
}

void Voice::setPatch(int patch) {
	patch_ = patch;
}

int Voice::getPatch() const {
	return patch_;
}

void Voice::setStemType(int stemType) {
	stemType_ = stemType;
}

int Voice::getStemType() const {
	return stemType_;
}

int Voice::getDefaultPatch() {
	return -1;
}

int Voice::getDefaultVolume() {
	return -1;
}

///////////////////////////////////////////////////////////////////////////////
Track::Track() {
	clear();
}

Track::~Track() {
	clear();
}

void Track::setName(const QString& str) {
	name_ = str;
}

QString Track::getName(void) const {
	return name_;
}

void Track::setBriefName(const QString& str) {
	briefName_ = str;
}

QString Track::getBriefName(void) const {
	return briefName_;
}

void Track::setPatch(unsigned int patch) {
	patch_ = patch;
}

unsigned int Track::getPatch() const {
	return patch_;
}

void Track::setChannel(int channel) {
	channel_ = channel;
}

int Track::getChannel() const {
	return channel_;
}

void Track::setShowName(bool show) {
	showName_ = show;
}

bool Track::getShowName() const {
	return showName_;
}

void Track::setShowBriefName(bool show) {
	showBriefName_ = show;
}

bool Track::getShowBriefName() const {
	return showBriefName_;
}

void Track::setMute(bool mute) {
	mute_ = mute;
}

bool Track::getMute() const {
	return mute_;
}

void Track::setSolo(bool solo) {
	solo_ = solo;
}

bool Track::getSolo() const {
	return solo_;
}

void Track::setShowKeyEachLine(bool show) {
	showKeyEachLine_ = show;
}

bool Track::getShowKeyEachLine() const {
	return showKeyEachLine_;
}

void Track::setVoiceCount(int voices) {
	voiceCount_ = voices;
}

int Track::getVoiceCount() const {
	return voiceCount_;
}

void Track::addVoice(Voice* voice) {
	voices_.push_back(voice);
}

QList<Voice*> Track::getVoices() const {
	return voices_;
}

void Track::setShowTranspose(bool show) {
	showTranspose_ = show;
}

bool Track::getShowTranspose() const {
	return showTranspose_;
}

void Track::setTranspose(int transpose) {
	transpose_ = transpose;
}

int Track::getTranspose() const {
	return transpose_;
}

void Track::setNoteShift(int shift) {
	noteShift_ = shift;
}

int Track::getNoteShift() const {
	return noteShift_;
}

void Track::setStartClef(int clef/*in Clef*/) {
	startClef_ = clef;
}

ClefType Track::getStartClef() const {
	return (ClefType)startClef_;
}

void Track::setTransposeClef(int clef) {
	transposeClef_ = clef;
}

int Track::getTansposeClef() const {
	return transposeClef_;
}

void Track::setStartKey(int key) {
	startKey_ = key;
}

int Track::getStartKey() const {
	return startKey_;
}

void Track::setDisplayPercent(unsigned int percent/*25~100?*/) {
	displayPercent_ = percent;
}

unsigned int Track::getDisplayPercent() const {
	return displayPercent_;
}

void Track::setShowLegerLine(bool show) {
	showLegerLine_ = show;
}

bool Track::getShowLegerLine() const {
	return showLegerLine_;
}

void Track::setShowClef(bool show) {
	showClef_ = show;
}

bool Track::getShowClef() const {
	return showClef_;
}

void Track::setShowTimeSignature(bool show) {
	showTimeSignature_ = show;
}

bool Track::getShowTimeSignature() const {
	return showTimeSignature_;
}

void Track::setShowKeySignature(bool show) {
	showKeySignature_ = show;
}

bool Track::getShowKeySignature() const {
	return showKeySignature_;
}

void Track::setShowBarline(bool show) {
	showBarline_ = show;
}

bool Track::getShowBarline() const {
	return showBarline_;
}

void Track::setFillWithRest(bool fill) {
	fillWithRest_ = fill;
}

bool Track::getFillWithRest() const {
	return fillWithRest_;
}

void Track::setFlatTail(bool flat) {
	flatTail_ = flat;
}

bool Track::getFlatTail() const {
	return flatTail_;
}

void Track::setShowClefEachLine(bool show) {
	showClefEachLine_ = show;
}

bool Track::getShowClefEachLine() const {
	return showClefEachLine_;
}

void Track::addDrum(const DrumNode& node) {
	/*DrumNode node;
	node.line_ = line;
	node.headType_ = headType;
	node.pitch_ = pitch;
	node.voice_ = voice;*/
	drumKit_.push_back(node);
}

QList<Track::DrumNode> Track::getDrumKit() const {
	return drumKit_;
}

void Track::setPart(int part) {
	part_ = part;
}

int Track::getPart() const {
	return part_;
}

void Track::clear(void) {
	number_ = 0;

	name_ = QString();

	patch_ = 0;
	channel_ = 0;
	transpose_ = 0;
	showTranspose_ = false;
	noteShift_ = 0;
	startClef_ = Clef_Treble;
	transposeClef_ = Clef_Treble;
	displayPercent_ = 100;
	startKey_ = 0;
	voiceCount_ = 8;

	showName_ = true;
	showBriefName_ = false;
	showKeyEachLine_ = false;
	showLegerLine_ = true;
	showClef_ = true;
	showTimeSignature_ = true;
	showKeySignature_ = true;
	showBarline_ = true;
	showClefEachLine_ = false;

	fillWithRest_ = true;
	flatTail_ = false;

	mute_ = false;
	solo_ = false;

	drumKit_.clear();

	part_ = 0;

	for(int i=0; i<voices_.size(); ++i){
		delete voices_[i];
	}
	voices_.clear();
}

///////////////////////////////////////////////////////////////////////////////
Page::Page() {
	beginLine_ = 0;
	lineCount_ = 0;

	lineInterval_ = 9;
	staffInterval_ = 7;
	staffInlineInterval_ = 6;

	lineBarCount_ = 4;
	pageLineCount_ = 5;

	leftMargin_ = 0xA8;
	topMargin_ = 0xA8;
	rightMargin_ = 0xA8;
	bottomMargin_ = 0xA8;

	pageWidth_ = 0x0B40;
	pageHeight_ = 0x0E90;
}

void Page::setBeginLine(int line) {
	beginLine_ = line;
}

int Page::getBeginLine() const {
	return beginLine_;
}

void Page::setLineCount(int count) {
	lineCount_ = count;
}

int Page::getLineCount() const {
	return lineCount_;
}

void Page::setLineInterval(int interval) {
	lineInterval_ = interval;
}

int Page::getLineInterval() const {
	return lineInterval_;
}

void Page::setStaffInterval(int interval) {
	staffInterval_ = interval;
}

int Page::getStaffInterval() const {
	return staffInterval_;
}

void Page::setStaffInlineInterval(int interval) {
	staffInlineInterval_ = interval;
}

int Page::getStaffInlineInterval() const {
	return staffInlineInterval_;
}

void Page::setLineBarCount(int count) {
	lineBarCount_ = count;
}

int Page::getLineBarCount() const {
	return lineBarCount_;
}

void Page::setPageLineCount(int count) {
	pageLineCount_ = count;
}

int Page::getPageLineCount() const {
	return pageLineCount_;
}

void Page::setLeftMargin(int margin) {
	leftMargin_ = margin;
}

int Page::getLeftMargin() const {
	return leftMargin_;
}

void Page::setTopMargin(int margin) {
	topMargin_ = margin;
}

int Page::getTopMargin() const {
	return topMargin_;
}

void Page::setRightMargin(int margin) {
	rightMargin_ = margin;
}

int Page::getRightMargin() const {
	return rightMargin_;
}

void Page::setBottomMargin(int margin) {
	bottomMargin_ = margin;
}

int Page::getBottomMargin() const {
	return bottomMargin_;
}

void Page::setPageWidth(int width) {
	pageWidth_ = width;
}

int Page::getPageWidth() const {
	return pageWidth_;
}

void Page::setPageHeight(int height) {
	pageHeight_ = height;
}

int Page::getPageHeight() const {
	return pageHeight_;
}

///////////////////////////////////////////////////////////////////////////////
Line::Line() {
	beginBar_ = 0;
	barCount_ = 0;
	yOffset_ = 0;
	leftXOffset_ = 0;
	rightXOffset_ = 0;
}

Line::~Line() {
	for(int i=0; i<staffs_.size(); ++i){
		delete staffs_[i];
	}
	staffs_.clear();
}

void Line::addStaff(Staff* staff) {
	staffs_.push_back(staff);
}

int Line::getStaffCount() const {
	return staffs_.size();
}

Staff* Line::getStaff(int idx) const {
	if (idx >= 0 && idx < (int) staffs_.size()) {
		return staffs_[idx];
	}

	return 0;
}

void Line::setBeginBar(unsigned int bar) {
	beginBar_ = bar;
}

unsigned int Line::getBeginBar() const {
	return beginBar_;
}

void Line::setBarCount(unsigned int count) {
	barCount_ = count;
}

unsigned int Line::getBarCount() const {
	return barCount_;
}

void Line::setYOffset(int offset) {
	yOffset_ = offset;
}

int Line::getYOffset() const {
	return yOffset_;
}

void Line::setLeftXOffset(int offset) {
	leftXOffset_ = offset;
}

int Line::getLeftXOffset() const {
	return leftXOffset_;
}

void Line::setRightXOffset(int offset) {
	rightXOffset_ = offset;
}

int Line::getRightXOffset() const {
	return rightXOffset_;
}

///////////////////////////////////////////////////////////////////////////////
Staff::Staff() {
	clef_ = Clef_Treble;
	key_ = 0;
	visible_ = true;
	groupType_ = Group_None;
	groupStaffCount_ = 0;
}

void Staff::setClefType(int clef) {
	clef_ = (ClefType) clef;
}

ClefType Staff::getClefType() const {
	return clef_;
}

void Staff::setKeyType(int key) {
	key_ = key;
}

int Staff::getKeyType() const {
	return key_;
}

void Staff::setVisible(bool visible) {
	visible_ = visible;
}

bool Staff::setVisible() const {
	return visible_;
}

void Staff::setGroupType(GroupType type){
	groupType_ = type;
}

GroupType Staff::getGroupType() const {
	return groupType_;
}

void Staff::setGroupStaffCount(int count) {
	groupStaffCount_ = count;
}

int Staff::getGroupStaffCount() const {
	return groupStaffCount_;
}

///////////////////////////////////////////////////////////////////////////////
Note::Note() {
	rest_ = false;
	note_ = 60;
	accidental_ = Accidental_Normal;
	showAccidental_ = false;
	offVelocity_ = 0x40;
	onVelocity_ = 0x50;
	headType_ = NoteHead_Standard;
	tiePos_ = Tie_None;
	offsetStaff_ = 0;
	show_ = true;
	offsetTick_ = 0;
}

void Note::setIsRest(bool rest) {
	rest_ = rest;
}

bool Note::getIsRest() const {
	return rest_;
}

void Note::setNote(unsigned int note) {
	note_ = note;
}

unsigned int Note::getNote() const {
	return note_;
}

void Note::setAccidental(int type) {
	accidental_ = (AccidentalType) type;
}

AccidentalType Note::getAccidental() const {
	return accidental_;
}

void Note::setShowAccidental(bool show) {
	showAccidental_ = show;
}

bool Note::getShowAccidental() const {
	return showAccidental_;
}

void Note::setOnVelocity(unsigned int velocity) {
	onVelocity_ = velocity;
}

unsigned int Note::getOnVelocity() const {
	return onVelocity_;
}

void Note::setOffVelocity(unsigned int velocity) {
	offVelocity_ = velocity;
}

unsigned int Note::getOffVelocity() const {
	return offVelocity_;
}

void Note::setHeadType(int type) {
	headType_ = (NoteHeadType) type;
}

NoteHeadType Note::getHeadType() const {
	return headType_;
}

void Note::setTiePos(int tiePos) {
	tiePos_ = (TiePos) tiePos;
}

TiePos Note::getTiePos() const {
	return tiePos_;
}

void Note::setOffsetStaff(int offset) {
	offsetStaff_ = offset;
}

int Note::getOffsetStaff() const {
	return offsetStaff_;
}

void Note::setShow(bool show) {
	show_ = show;
}

bool Note::getShow() const {
	return show_;
}

void Note::setOffsetTick(int offset) {
	offsetTick_ = offset;
}

int Note::getOffsetTick() const {
	return offsetTick_;
}

///////////////////////////////////////////////////////////////////////////////
Articulation::Articulation() {
	type_ = Articulation_Marcato;
	above_ = true;

	changeSoundEffect_ = false;
	changeLength_ = false;
	changeVelocity_ = false;
	changeExtraLength_ = false;

	soundEffect_ = qMakePair(0, 0);
	lengthPercentage_ = 100;
	velocityType_ = Velocity_Offset;
	velocityValue_ = 0;
	extraLength_ = 0;

	trillNoteLength_ = 60;
	trillRate_ = Note_Sixteen;
	accelerateType_ = Accelerate_None;
	auxiliaryFirst_ = false;
	trillInterval_ = TrillInterval_Chromatic;
}

void Articulation::setArtType(int type) {
	type_ = (ArticulationType) type;
}

ArticulationType Articulation::getArtType() const {
	return type_;
}

void Articulation::setPlacementAbove(bool above) {
	above_ = above;
}

bool Articulation::getPlacementAbove() const {
	return above_;
}

bool Articulation::getChangeSoundEffect() const {
	return changeSoundEffect_;
}

void Articulation::setSoundEffect(int soundFrom, int soundTo) {
	soundEffect_ = qMakePair(soundFrom, soundTo);
	changeSoundEffect_ = true;
}

QPair<int, int> Articulation::getSoundEffect() const {
	return soundEffect_;
}

bool Articulation::getChangeLength() const {
	return changeLength_;
}

void Articulation::setLengthPercentage(int percentage) {
	lengthPercentage_ = percentage;
	changeLength_ = true;
}

int Articulation::getLengthPercentage() const {
	return lengthPercentage_;
}

bool Articulation::getChangeVelocity() const {
	return changeVelocity_;
}

void Articulation::setVelocityType(VelocityType type) {
	velocityType_ = type;
	changeVelocity_ = true;
}

Articulation::VelocityType Articulation::getVelocityType() const {
	return velocityType_;
}

void Articulation::setVelocityValue(int value) {
	velocityValue_ = value;
}

int Articulation::getVelocityValue() const {
	return velocityValue_;
}

bool Articulation::getChangeExtraLength() const {
	return changeExtraLength_;
}

void Articulation::setExtraLength(int length) {
	extraLength_ = length;
	changeExtraLength_ = true;
}

int Articulation::getExtraLength() const {
	return extraLength_;
}

void Articulation::setTrillNoteLength(int length) {
	trillNoteLength_ = length;
}

int Articulation::getTrillNoteLength() const {
	return trillNoteLength_;
}

void Articulation::setTrillRate(NoteType rate) {
	trillRate_ = rate;
}

NoteType Articulation::getTrillRate() const {
	return trillRate_;
}

void Articulation::setAccelerateType(int type) {
	accelerateType_ = (AccelerateType) type;
}

Articulation::AccelerateType Articulation::getAccelerateType() const {
	return accelerateType_;
}

void Articulation::setAuxiliaryFirst(bool first) {
	auxiliaryFirst_ = first;
}

bool Articulation::getAuxiliaryFirst() const {
	return auxiliaryFirst_;
}

void Articulation::setTrillInterval(int interval) {
	trillInterval_ = (TrillInterval) interval;
}

Articulation::TrillInterval Articulation::getTrillInterval() const {
	return trillInterval_;
}

bool Articulation::willAffectNotes() const {
	bool affect = false;

	switch (getArtType()) {
	case Articulation_Major_Trill:
	case Articulation_Minor_Trill:
	case Articulation_Trill_Section:
	case Articulation_Inverted_Short_Mordent:
	case Articulation_Inverted_Long_Mordent:
	case Articulation_Short_Mordent:
	case Articulation_Turn:

	case Articulation_Arpeggio:
	case Articulation_Tremolo_Eighth:
	case Articulation_Tremolo_Sixteenth:
	case Articulation_Tremolo_Thirty_Second:
	case Articulation_Tremolo_Sixty_Fourth: {
		affect = true;
		break;
	}
	case Articulation_Finger_1:
	case Articulation_Finger_2:
	case Articulation_Finger_3:
	case Articulation_Finger_4:
	case Articulation_Finger_5:
	case Articulation_Flat_Accidental_For_Trill:
	case Articulation_Sharp_Accidental_For_Trill:
	case Articulation_Natural_Accidental_For_Trill:
	case Articulation_Marcato:
	case Articulation_Marcato_Dot:
	case Articulation_Heavy_Attack:
	case Articulation_SForzando:
	case Articulation_SForzando_Dot:
	case Articulation_Heavier_Attack:
	case Articulation_SForzando_Inverted:
	case Articulation_SForzando_Dot_Inverted:
	case Articulation_Staccatissimo:
	case Articulation_Staccato:
	case Articulation_Tenuto:
	case Articulation_Up_Bow:
	case Articulation_Down_Bow:
	case Articulation_Up_Bow_Inverted:
	case Articulation_Down_Bow_Inverted:
	case Articulation_Natural_Harmonic:
	case Articulation_Artificial_Harmonic:
	case Articulation_Plus_Sign:
	case Articulation_Fermata:
	case Articulation_Fermata_Inverted:
	case Articulation_Pedal_Down:
	case Articulation_Pedal_Up:
	case Articulation_Pause:
	case Articulation_Grand_Pause:
	case Articulation_Toe_Pedal:
	case Articulation_Heel_Pedal:
	case Articulation_Toe_To_Heel_Pedal:
	case Articulation_Heel_To_Toe_Pedal:
	case Articulation_Open_String:
	case Articulation_Guitar_Lift:
	case Articulation_Guitar_Slide_Up:
	case Articulation_Guitar_Rip:
	case Articulation_Guitar_Fall_Off:
	case Articulation_Guitar_Slide_Down:
	case Articulation_Guitar_Spill:
	case Articulation_Guitar_Flip:
	case Articulation_Guitar_Smear:
	case Articulation_Guitar_Bend:
	case Articulation_Guitar_Doit:
	case Articulation_Guitar_Plop:
	case Articulation_Guitar_Wow_Wow:
	case Articulation_Guitar_Thumb:
	case Articulation_Guitar_Index_Finger:
	case Articulation_Guitar_Middle_Finger:
	case Articulation_Guitar_Ring_Finger:
	case Articulation_Guitar_Pinky_Finger:
	case Articulation_Guitar_Tap:
	case Articulation_Guitar_Hammer:
	case Articulation_Guitar_Pluck: {
		break;
	}
	default:
		break;
	}

	return affect;
}

bool Articulation::isTrill(ArticulationType type) {
	bool isTrill = false;

	switch (type) {
	case Articulation_Major_Trill:
	case Articulation_Minor_Trill:
	case Articulation_Trill_Section: {
		isTrill = true;
		break;
	}
	default:
		break;
	}

	return isTrill;
}

Articulation::XmlType Articulation::getXmlType() const {
	XmlType xmlType = Xml_Unknown;

	switch (type_) {
	case Articulation_Major_Trill:
	case Articulation_Minor_Trill:
	case Articulation_Trill_Section:
	case Articulation_Inverted_Short_Mordent:
	case Articulation_Inverted_Long_Mordent:
	case Articulation_Short_Mordent:
	case Articulation_Turn:
		//	case Articulation_Flat_Accidental_For_Trill :
		//	case Articulation_Sharp_Accidental_For_Trill :
		//	case Articulation_Natural_Accidental_For_Trill :
	case Articulation_Tremolo_Eighth:
	case Articulation_Tremolo_Sixteenth:
	case Articulation_Tremolo_Thirty_Second:
	case Articulation_Tremolo_Sixty_Fourth: {
		xmlType = Xml_Ornament;
		break;
	}
	case Articulation_Marcato:
	case Articulation_Marcato_Dot:
	case Articulation_Heavy_Attack:
	case Articulation_SForzando:
	case Articulation_SForzando_Inverted:
	case Articulation_SForzando_Dot:
	case Articulation_SForzando_Dot_Inverted:
	case Articulation_Heavier_Attack:
	case Articulation_Staccatissimo:
	case Articulation_Staccato:
	case Articulation_Tenuto:
	case Articulation_Pause:
	case Articulation_Grand_Pause: {
		xmlType = Xml_Articulation;
		break;
	}
	case Articulation_Up_Bow:
	case Articulation_Down_Bow:
	case Articulation_Up_Bow_Inverted:
	case Articulation_Down_Bow_Inverted:
	case Articulation_Natural_Harmonic:
	case Articulation_Artificial_Harmonic:
	case Articulation_Finger_1:
	case Articulation_Finger_2:
	case Articulation_Finger_3:
	case Articulation_Finger_4:
	case Articulation_Finger_5:
	case Articulation_Plus_Sign: {
		xmlType = Xml_Technical;
		break;
	}
	case Articulation_Arpeggio: {
		xmlType = Xml_Arpeggiate;
		break;
	}
	case Articulation_Fermata:
	case Articulation_Fermata_Inverted: {
		xmlType = Xml_Fermata;
		break;
	}
	case Articulation_Pedal_Down:
	case Articulation_Pedal_Up: {
		xmlType = Xml_Direction;
		break;
	}
		//	case Articulation_Toe_Pedal :
		//	case Articulation_Heel_Pedal :
		//	case Articulation_Toe_To_Heel_Pedal :
		//	case Articulation_Heel_To_Toe_Pedal :
		//	case Articulation_Open_String :
	default:
		break;
	}

	return xmlType;
}

///////////////////////////////////////////////////////////////////////////////
NoteContainer::NoteContainer() {
	musicDataType_ = MusicData_Note_Container;

	grace_ = false;
	cue_ = false;
	rest_ = false;
	raw_ = false;
	noteType_ = Note_Quarter;
	dot_ = 0;
	graceNoteType_ = Note_Eight;
	stemUp_ = true;
	showStem_ = true;
	stemLength_ = 7;
	inBeam_ = false;
	tuplet_ = 0;
	space_ = 2;//div by 0
	noteShift_ = 0;
}

NoteContainer::~NoteContainer(){
	for(int i=0; i<notes_.size(); ++i){
		delete notes_[i];
	}
	for(int i=0; i<articulations_.size(); ++i){
		delete articulations_[i];
	}
	notes_.clear();
	articulations_.clear();
}

void NoteContainer::setIsGrace(bool grace) {
	grace_ = grace;
}

bool NoteContainer::getIsGrace() const {
	return grace_;
}

void NoteContainer::setIsCue(bool cue) {
	cue_ = cue;
}

bool NoteContainer::getIsCue() const {
	return cue_;
}

void NoteContainer::setIsRest(bool rest) {
	rest_ = rest;
}

bool NoteContainer::getIsRest() const {
	return rest_;
}

void NoteContainer::setIsRaw(bool raw) {
	raw_ = raw;
}

bool NoteContainer::getIsRaw() const {
	return raw_;
}

void NoteContainer::setNoteType(NoteType type) {
	noteType_ = Note_Quarter;

	switch (type) {
	case Note_DoubleWhole:
	case Note_Whole:
	case Note_Half:
	case Note_Quarter:
	case Note_Eight:
	case Note_Sixteen:
	case Note_32:
	case Note_64:
	case Note_128:
	case Note_256: {
		noteType_ = type;
		break;
	}
	default: {
		break;
	}
	}
}

NoteType NoteContainer::getNoteType() const {
	return noteType_;
}

void NoteContainer::setDot(int dot) {
	dot_ = dot;
}

int NoteContainer::getDot() const {
	return dot_;
}

void NoteContainer::setGraceNoteType(NoteType type) {
	graceNoteType_ = type;
}

NoteType NoteContainer::getGraceNoteType() const {
	return graceNoteType_;
}

void NoteContainer::setInBeam(bool in) {
	inBeam_ = in;
}

bool NoteContainer::getInBeam() const {
	return inBeam_;
}

void NoteContainer::setStemUp(bool up) {
	stemUp_ = up;
}

bool NoteContainer::getStemUp(void) const {
	return stemUp_;
}

void NoteContainer::setShowStem(bool show) {
	showStem_ = show;
}

bool NoteContainer::getShowStem() const {
	return showStem_;
}

void NoteContainer::setStemLength(int line) {
	stemLength_ = line;
}

int NoteContainer::getStemLength() const {
	return stemLength_;
}

void NoteContainer::setTuplet(int tuplet) {
	tuplet_ = tuplet;
}

int NoteContainer::getTuplet() const {
	return tuplet_;
}

void NoteContainer::setSpace(int space) {
	space_ = space;
}

int NoteContainer::getSpace() const {
	return space_;
}

void NoteContainer::addNoteRest(Note* note) {
	notes_.push_back(note);
}

QList<Note*> NoteContainer::getNotesRests() const {
	return notes_;
}

void NoteContainer::addArticulation(Articulation* art) {
	articulations_.push_back(art);
}

QList<Articulation*> NoteContainer::getArticulations() const {
	return articulations_;
}

void NoteContainer::setNoteShift(int octave) {
	noteShift_ = octave;
}

int NoteContainer::getNoteShift() const {
	return noteShift_;
}

int NoteContainer::getOffsetStaff() const {
	if(getIsRest())
		return 0;

	int staffMove = 0;
	QList<OVE::Note*> notes = getNotesRests();
	for (int i = 0; i < notes.size(); ++i) {
		OVE::Note* notePtr = notes[i];
		staffMove = notePtr->getOffsetStaff();
	}

	return staffMove;
}

int NoteContainer::getDuration() const {
	int duration = (int) NoteDuration_4;

	switch (noteType_) {
	case Note_DoubleWhole: {
		duration = (int) NoteDuration_Double_Whole;
		break;
	}
	case Note_Whole: {
		duration = (int) NoteDuration_Whole;
		break;
	}
	case Note_Half: {
		duration = (int) NoteDuration_2;
		break;
	}
	case Note_Quarter: {
		duration = (int) NoteDuration_4;
		break;
	}
	case Note_Eight: {
		duration = (int) NoteDuration_8;
		break;
	}
	case Note_Sixteen: {
		duration = (int) NoteDuration_16;
		break;
	}
	case Note_32: {
		duration = (int) NoteDuration_32;
		break;
	}
	case Note_64: {
		duration = (int) NoteDuration_64;
		break;
	}
	case Note_128: {
		duration = (int) NoteDuration_128;
		break;
	}
	case Note_256: {
		duration = (int) NoteDuration_256;
		break;
	}
	default:
		break;
	}

	int dotLength = duration;

	for (int i = 0; i < dot_; ++i) {
		dotLength /= 2;
	}

	dotLength = duration - dotLength;

	duration += dotLength;

	return duration;
}

///////////////////////////////////////////////////////////////////////////////
Beam::Beam() {
	musicDataType_ = MusicData_Beam;
	grace_ = false;
}

void Beam::setIsGrace(bool grace) {
	grace_ = grace;
}

bool Beam::getIsGrace() const {
	return grace_;
}

void Beam::addLine(const MeasurePos& startMp, const MeasurePos& endMp) {
	lines_.push_back(qMakePair(startMp, endMp));
}

const QList<QPair<MeasurePos, MeasurePos> > Beam::getLines() const {
	return lines_;
}

///////////////////////////////////////////////////////////////////////////////
Tie::Tie() {
	musicDataType_ = MusicData_Tie;

	showOnTop_ = true;
	note_ = 72;
	height_ = 24;
}

void Tie::setShowOnTop(bool top) {
	showOnTop_ = top;
}

bool Tie::getShowOnTop() const {
	return showOnTop_;
}

void Tie::setNote(int note) {
	note_ = note;
}

int Tie::getNote() const {
	return note_;
}

void Tie::setHeight(int height) {
	height_ = height;
}

int Tie::getHeight() const {
	return height_;
}

///////////////////////////////////////////////////////////////////////////////
Glissando::Glissando() {
	musicDataType_ = MusicData_Glissando;

	straight_ = true;
	text_ = "gliss.";
	lineThick_ = 8;
}

void Glissando::setStraightWavy(bool straight) {
	straight_ = straight;
}

bool Glissando::getStraightWavy() const {
	return straight_;
}

void Glissando::setText(const QString& text) {
	text_ = text;
}

QString Glissando::getText() const {
	return text_;
}

void Glissando::setLineThick(int thick) {
	lineThick_ = thick;
}

int Glissando::getLineThick() const {
	return lineThick_;
}

///////////////////////////////////////////////////////////////////////////////
Decorator::Decorator() :
	decoratorType_(Decorator_Articulation),
	artType_(Articulation_Marcato) {
	musicDataType_ = MusicData_Decorator;
}

void Decorator::setDecoratorType(DecoratorType type) {
	decoratorType_ = type;
}

Decorator::DecoratorType Decorator::getDecoratorType() const {
	return decoratorType_;
}

void Decorator::setArticulationType(ArticulationType type) {
	artType_ = type;
}

ArticulationType Decorator::getArticulationType() const {
	return artType_;
}

///////////////////////////////////////////////////////////////////////////////
MeasureRepeat::MeasureRepeat() {
	musicDataType_ = MusicData_Measure_Repeat;
	singleRepeat_ = true;
}

void MeasureRepeat::setSingleRepeat(bool single) {
	singleRepeat_ = single;

	start()->setMeasure(0);
	start()->setOffset(0);
	stop()->setMeasure(single ? 1 : 2);
	stop()->setOffset(0);
}

bool MeasureRepeat::getSingleRepeat() const {
	return singleRepeat_;
}

///////////////////////////////////////////////////////////////////////////////
Tuplet::Tuplet() :
	tuplet_(3), space_(2), height_(0), noteType_(Note_Quarter){
	musicDataType_ = MusicData_Tuplet;
	mark_ = new OffsetElement();
}

Tuplet::~Tuplet(){
	delete mark_;
}

void Tuplet::setTuplet(int tuplet) {
	tuplet_ = tuplet;
}

int Tuplet::getTuplet() const {
	return tuplet_;
}

void Tuplet::setSpace(int space) {
	space_ = space;
}

int Tuplet::getSpace() const {
	return space_;
}

OffsetElement* Tuplet::getMarkHandle() const {
	return mark_;
}

void Tuplet::setHeight(int height) {
	height_ = height;
}

int Tuplet::getHeight() const {
	return height_;
}

void Tuplet::setNoteType(NoteType type) {
	noteType_ = type;
}

NoteType Tuplet::getNoteType() const {
	return noteType_;
}

///////////////////////////////////////////////////////////////////////////////
Harmony::Harmony() {
	musicDataType_ = MusicData_Harmony;

	harmonyType_ = Harmony_maj;
	root_ = 0;
	bass_ = -1;//0xff
	bassOnBottom_ = false;
	angle_ = 0;
}

void Harmony::setHarmonyType(HarmonyType type) {
	harmonyType_ = type;
}

HarmonyType Harmony::getHarmonyType() const {
	return harmonyType_;
}

void Harmony::setRoot(int root) {
	root_ = root;
}

int Harmony::getRoot() const {
	return root_;
}

void Harmony::setBass(int bass) {
	bass_ = bass;
}

int Harmony::getBass() const {
	return bass_;
}

void Harmony::setBassOnBottom(bool on) {
	bassOnBottom_ = on;
}

bool Harmony::getBassOnBottom() const {
	return bassOnBottom_;
}

void Harmony::setAngle(int angle) {
	angle_ = angle;
}

int Harmony::getAngle() const {
	return angle_;
}

///////////////////////////////////////////////////////////////////////////////
Clef::Clef() {
	musicDataType_ = MusicData_Clef;

	clefType_ = Clef_Treble;
}

void Clef::setClefType(int type) {
	clefType_ = (ClefType) type;
}

ClefType Clef::getClefType() const {
	return clefType_;
}

///////////////////////////////////////////////////////////////////////////////
Lyric::Lyric() {
	musicDataType_ = MusicData_Lyric;

	lyric_ = QString();
	verse_ = 0;
}

void Lyric::setLyric(const QString& lyricText) {
	lyric_ = lyricText;
}

QString Lyric::getLyric() const {
	return lyric_;
}

void Lyric::setVerse(int verse) {
	verse_ = verse;
}

int Lyric::getVerse() const {
	return verse_;
}

///////////////////////////////////////////////////////////////////////////////
Slur::Slur() {
	musicDataType_ = MusicData_Slur;

	containerCount_ = 1;
	showOnTop_ = true;
	noteTimePercent_ = 100;

	handle_2_ = new OffsetElement();
	handle_3_ = new OffsetElement();
}

Slur::~Slur() {
	delete handle_2_;
	delete handle_3_;
}

void Slur::setContainerCount(int count) {
	containerCount_ = count;
}

int Slur::getContainerCount() const {
	return containerCount_;
}

void Slur::setShowOnTop(bool top) {
	showOnTop_ = top;
}

bool Slur::getShowOnTop() const {
	return showOnTop_;
}

OffsetElement* Slur::getHandle2() const {
	return handle_2_;
}

OffsetElement* Slur::getHandle3() const {
	return handle_3_;
}

void Slur::setNoteTimePercent(int percent) {
	noteTimePercent_ = percent;
}

int Slur::getNoteTimePercent() const {
	return noteTimePercent_;
}

///////////////////////////////////////////////////////////////////////////////
Dynamics::Dynamics() {
	musicDataType_ = MusicData_Dynamics;

	dynamicsType_ = Dynamics_pppp;
	playback_ = true;
	velocity_ = 30;
}

void Dynamics::setDynamicsType(int type) {
	dynamicsType_ = (DynamicsType) type;
}

DynamicsType Dynamics::getDynamicsType() const {
	return dynamicsType_;
}

void Dynamics::setIsPlayback(bool play) {
	playback_ = play;
}

bool Dynamics::getIsPlayback() const {
	return playback_;
}

void Dynamics::setVelocity(int vel) {
	velocity_ = vel;
}

int Dynamics::getVelocity() const {
	return velocity_;
}

///////////////////////////////////////////////////////////////////////////////
WedgeEndPoint::WedgeEndPoint() {
	musicDataType_ = MusicData_Wedge_EndPoint;

	wedgeType_ = Wedge_Cres;
	height_ = 24;
	wedgeStart_ = true;
}

void WedgeEndPoint::setWedgeType(WedgeType type) {
	wedgeType_ = type;
}

WedgeType WedgeEndPoint::getWedgeType() const {
	return wedgeType_;
}

void WedgeEndPoint::setHeight(int height) {
	height_ = height;
}

int WedgeEndPoint::getHeight() const {
	return height_;
}

void WedgeEndPoint::setWedgeStart(bool wedgeStart) {
	wedgeStart_ = wedgeStart;
}

bool WedgeEndPoint::getWedgeStart() const {
	return wedgeStart_;
}

///////////////////////////////////////////////////////////////////////////////
Wedge::Wedge() {
	musicDataType_ = MusicData_Wedge;

	wedgeType_ = Wedge_Cres;
	height_ = 24;
}

void Wedge::setWedgeType(WedgeType type) {
	wedgeType_ = type;
}

WedgeType Wedge::getWedgeType() const {
	return wedgeType_;
}

void Wedge::setHeight(int height) {
	height_ = height;
}

int Wedge::getHeight() const {
	return height_;
}

///////////////////////////////////////////////////////////////////////////////
Pedal::Pedal() {
	musicDataType_ = MusicData_Pedal;

	half_ = false;
	playback_ = false;
	playOffset_ = 0;

	pedalHandle_ = new OffsetElement();
}

Pedal::~Pedal() {
	delete pedalHandle_;
}

void Pedal::setHalf(bool half) {
	half_ = half;
}

bool Pedal::getHalf() const {
	return half_;
}

OffsetElement* Pedal::getPedalHandle() const {
	return pedalHandle_;
}

void Pedal::setIsPlayback(bool playback) {
	playback_ = playback;
}

bool Pedal::getIsPlayback() const {
	return playback_;
}

void Pedal::setPlayOffset(int offset) {
	playOffset_ = offset;
}

int Pedal::getPlayOffset() const {
	return playOffset_;
}

///////////////////////////////////////////////////////////////////////////////
KuoHao::KuoHao() {
	musicDataType_ = MusicData_KuoHao;

	kuohaoType_ = KuoHao_Parentheses;
	height_ = 0;
}

void KuoHao::setHeight(int height) {
	height_ = height;
}

int KuoHao::getHeight() const {
	return height_;
}

void KuoHao::setKuohaoType(int type) {
	kuohaoType_ = (KuoHaoType) type;
}

KuoHaoType KuoHao::getKuohaoType() const {
	return kuohaoType_;
}

///////////////////////////////////////////////////////////////////////////////
Expressions::Expressions() {
	musicDataType_ = MusicData_Expressions;

	text_ = QString();
}

void Expressions::setText(const QString& str) {
	text_ = str;
}

QString Expressions::getText() const {
	return text_;
}

///////////////////////////////////////////////////////////////////////////////
HarpPedal::HarpPedal() :
	showType_(0),
	showCharFlag_(0) {
	musicDataType_ = MusicData_Harp_Pedal;
}

void HarpPedal::setShowType(int type) {
	showType_ = type;
}

int HarpPedal::getShowType() const {
	return showType_;
}

void HarpPedal::setShowCharFlag(int flag) {
	showCharFlag_ = flag;
}

int HarpPedal::getShowCharFlag() const {
	return showCharFlag_;
}

///////////////////////////////////////////////////////////////////////////////
OctaveShift::OctaveShift() :
	octaveShiftType_(OctaveShift_8),
	octaveShiftPosition_(OctavePosition_Start),
	endTick_(0) {
	musicDataType_ = MusicData_OctaveShift;
}

void OctaveShift::setOctaveShiftType(int type) {
	octaveShiftType_ = (OctaveShiftType) type;
}

OctaveShiftType OctaveShift::getOctaveShiftType() const {
	return octaveShiftType_;
}

int OctaveShift::getNoteShift() const {
	int shift = 12;

	switch (getOctaveShiftType()) {
	case OctaveShift_8: {
		shift = 12;
		break;
	}
	case OctaveShift_Minus_8: {
		shift = -12;
		break;
	}
	case OctaveShift_15: {
		shift = 24;
		break;
	}
	case OctaveShift_Minus_15: {
		shift = -24;
		break;
	}
	default:
		break;
	}

	return shift;
}

void OctaveShift::setEndTick(int tick) {
	endTick_ = tick;
}

int OctaveShift::getEndTick() const {
	return endTick_;
}

///////////////////////////////////////////////////////////////////////////////
OctaveShiftEndPoint::OctaveShiftEndPoint() {
	musicDataType_ = MusicData_OctaveShift_EndPoint;

	octaveShiftType_ = OctaveShift_8;
	octaveShiftPosition_ = OctavePosition_Start;
	endTick_ = 0;
}

void OctaveShiftEndPoint::setOctaveShiftType(int type) {
	octaveShiftType_ = (OctaveShiftType) type;
}

OctaveShiftType OctaveShiftEndPoint::getOctaveShiftType() const {
	return octaveShiftType_;
}

void OctaveShiftEndPoint::setOctaveShiftPosition(int position) {
	octaveShiftPosition_ = (OctaveShiftPosition) position;
}

OctaveShiftPosition OctaveShiftEndPoint::getOctaveShiftPosition() const {
	return octaveShiftPosition_;
}

void OctaveShiftEndPoint::setEndTick(int tick) {
	endTick_ = tick;
}

int OctaveShiftEndPoint::getEndTick() const {
	return endTick_;
}

///////////////////////////////////////////////////////////////////////////////
MultiMeasureRest::MultiMeasureRest() {
	musicDataType_ = MusicData_Multi_Measure_Rest;
	measureCount_ = 0;
}

void MultiMeasureRest::setMeasureCount(int count) {
	measureCount_ = count;
}

int MultiMeasureRest::getMeasureCount() const {
	return measureCount_;
}

///////////////////////////////////////////////////////////////////////////////
Tempo::Tempo() {
	musicDataType_ = MusicData_Tempo;

	leftNoteType_ = 3;
	showMark_ = false;
	showText_ = false;
	showParenthesis_ = false;
	typeTempo_ = 96;
	leftText_ = QString();
	rightText_ = QString();
	swingEighth_ = false;
	rightNoteType_ = 3;
}

void Tempo::setLeftNoteType(int type) {
	leftNoteType_ = type;
}

NoteType Tempo::getLeftNoteType() const {
	return (NoteType) leftNoteType_;
}

void Tempo::setShowMark(bool show) {
	showMark_ = show;
}

bool Tempo::getShowMark() const {
	return showMark_;
}

void Tempo::setShowBeforeText(bool show) {
	showText_ = show;
}

bool Tempo::getShowBeforeText() const {
	return showText_;
}

void Tempo::setShowParenthesis(bool show) {
	showParenthesis_ = show;
}

bool Tempo::getShowParenthesis() const {
	return showParenthesis_;
}

void Tempo::setTypeTempo(int tempo) {
	typeTempo_ = tempo;
}

int Tempo::getTypeTempo() const {
	return typeTempo_;
}

int Tempo::getQuarterTempo() const {
	double factor = pow(2.0, (int) Note_Quarter - (int) getLeftNoteType());
	int tempo = int((double) getTypeTempo() * factor);

	return tempo;
}

void Tempo::setLeftText(const QString& str) {
	leftText_ = str;
}

QString Tempo::getLeftText() const {
	return leftText_;
}

void Tempo::setRightText(const QString& str) {
	rightText_ = str;
}

QString Tempo::getRightText() const {
	return rightText_;
}

void Tempo::setSwingEighth(bool swing) {
	swingEighth_ = swing;
}

bool Tempo::getSwingEighth() const {
	return swingEighth_;
}

void Tempo::setRightNoteType(int type) {
	rightNoteType_ = type;
}

int Tempo::getRightNoteType() const {
	return rightNoteType_;
}

///////////////////////////////////////////////////////////////////////////////
Text::Text() {
	musicDataType_ = MusicData_Text;

	textType_ = Text_Rehearsal;
	horiMargin_ = 8;
	vertMargin_ = 8;
	lineThick_ = 4;
	text_ = QString();
	width_ = 0;
	height_ = 0;
}

void Text::setTextType(TextType type) {
	textType_ = type;
}

Text::TextType Text::getTextType() const {
	return textType_;
}

void Text::setHorizontalMargin(int margin) {
	horiMargin_ = margin;
}

int Text::getHorizontalMargin() const {
	return horiMargin_;
}

void Text::setVerticalMargin(int margin) {
	vertMargin_ = margin;
}

int Text::getVerticalMargin() const {
	return vertMargin_;
}

void Text::setLineThick(int thick) {
	lineThick_ = thick;
}

int Text::getLineThick() const {
	return lineThick_;
}

void Text::setText(const QString& text) {
	text_ = text;
}

QString Text::getText() const {
	return text_;
}

void Text::setWidth(int width) {
	width_ = width;
}

int Text::getWidth() const {
	return width_;
}

void Text::setHeight(int height) {
	height_ = height;
}

int Text::getHeight() const {
	return height_;
}

///////////////////////////////////////////////////////////////////////////////
TimeSignature::TimeSignature() {
	numerator_ = 4;
	denominator_ = 4;
	isSymbol_ = false;
	beatLength_ = 480;
	barLength_ = 1920;
	barLengthUnits_ = 0x400;
	replaceFont_ = false;
	showBeatGroup_ = false;

	groupNumerator1_ = 0;
	groupNumerator2_ = 0;
	groupNumerator3_ = 0;
	groupDenominator1_ = 4;
	groupDenominator2_ = 4;
	groupDenominator3_ = 4;

	beamGroup1_ = 4;
	beamGroup2_ = 0;
	beamGroup3_ = 0;
	beamGroup4_ = 0;

	beamCount16th_ = 4;
	beamCount32th_ = 1;
}

void TimeSignature::setNumerator(int numerator) {
	numerator_ = numerator;
}

int TimeSignature::getNumerator() const {
	return numerator_;
}

void TimeSignature::setDenominator(int denominator) {
	denominator_ = denominator;
}

int TimeSignature::getDenominator() const {
	return denominator_;
}

void TimeSignature::setIsSymbol(bool symbol) {
	isSymbol_ = symbol;
}

bool TimeSignature::getIsSymbol() const {
	if (numerator_ == 2 && denominator_ == 2) {
		return true;
	}

	return isSymbol_;
}

void TimeSignature::setBeatLength(int length) {
	beatLength_ = length;
}

int TimeSignature::getBeatLength() const {
	return beatLength_;
}

void TimeSignature::setBarLength(int length) {
	barLength_ = length;
}

int TimeSignature::getBarLength() const {
	return barLength_;
}

void TimeSignature::addBeat(int startUnit, int lengthUnit, int startTick) {
	BeatNode node;
	node.startUnit_ = startUnit;
	node.lengthUnit_ = lengthUnit;
	node.startTick_ = startTick;
	beats_.push_back(node);
}

void TimeSignature::endAddBeat() {
	barLengthUnits_ = 0;

	for (int i = 0; i < beats_.size(); ++i) {
		barLengthUnits_ += beats_[i].lengthUnit_;
	}
}

int TimeSignature::getUnits() const {
	return barLengthUnits_;
}

void TimeSignature::setReplaceFont(bool replace) {
	replaceFont_ = replace;
}

bool TimeSignature::getReplaceFont() const {
	return replaceFont_;
}

void TimeSignature::setShowBeatGroup(bool show) {
	showBeatGroup_ = show;
}

bool TimeSignature::getShowBeatGroup() const {
	return showBeatGroup_;
}

void TimeSignature::setGroupNumerator1(int numerator) {
	groupNumerator1_ = numerator;
}

void TimeSignature::setGroupNumerator2(int numerator) {
	groupNumerator2_ = numerator;
}

void TimeSignature::setGroupNumerator3(int numerator) {
	groupNumerator3_ = numerator;
}

void TimeSignature::setGroupDenominator1(int denominator) {
	groupDenominator1_ = denominator;
}

void TimeSignature::setGroupDenominator2(int denominator) {
	groupDenominator2_ = denominator;
}

void TimeSignature::setGroupDenominator3(int denominator) {
	groupDenominator3_ = denominator;
}

void TimeSignature::setBeamGroup1(int count) {
	beamGroup1_ = count;
}

void TimeSignature::setBeamGroup2(int count) {
	beamGroup2_ = count;
}

void TimeSignature::setBeamGroup3(int count) {
	beamGroup3_ = count;
}

void TimeSignature::setBeamGroup4(int count) {
	beamGroup4_ = count;
}

void TimeSignature::set16thBeamCount(int count) {
	beamCount16th_ = count;
}

void TimeSignature::set32thBeamCount(int count) {
	beamCount32th_ = count;
}

///////////////////////////////////////////////////////////////////////////////
Key::Key() {
	key_ = 0;
	set_ = false;
	previousKey_ = 0;
	symbolCount_ = 0;
}

void Key::setKey(int key) {
	key_ = key;
	set_ = true;
}

int Key::getKey() const {
	return key_;
}

bool Key::getSetKey() const {
	return set_;
}

void Key::setPreviousKey(int key) {
	previousKey_ = key;
}

int Key::getPreviousKey() const {
	return previousKey_;
}

void Key::setSymbolCount(int count) {
	symbolCount_ = count;
}

int Key::getSymbolCount() const {
	return symbolCount_;
}

///////////////////////////////////////////////////////////////////////////////
RepeatSymbol::RepeatSymbol() :
	text_("#1"), repeatType_(Repeat_Segno) {
	musicDataType_ = MusicData_Repeat;
}

void RepeatSymbol::setText(const QString& text) {
	text_ = text;
}

QString RepeatSymbol::getText() const {
	return text_;
}

void RepeatSymbol::setRepeatType(int repeatType) {
	repeatType_ = (RepeatType) repeatType;
}

RepeatType RepeatSymbol::getRepeatType() const {
	return repeatType_;
}

///////////////////////////////////////////////////////////////////////////////
NumericEnding::NumericEnding() {
	musicDataType_ = MusicData_Numeric_Ending;

	height_ = 0;
	text_ = QString();
	numericHandle_ = new OffsetElement();
}

NumericEnding::~NumericEnding() {
	delete numericHandle_;
}

OffsetElement* NumericEnding::getNumericHandle() const {
	return numericHandle_;
}

void NumericEnding::setHeight(int height) {
	height_ = height;
}

int NumericEnding::getHeight() const {
	return height_;
}

void NumericEnding::setText(const QString& text) {
	text_ = text;
}

QString NumericEnding::getText() const {
	return text_;
}

QList<int> NumericEnding::getNumbers() const {
	int i;
	QStringList strs = text_.split(",", QString::SkipEmptyParts);
	QList<int> endings;

	for (i = 0; i < strs.size(); ++i) {
		bool ok;
		int num = strs[i].toInt(&ok);
		endings.push_back(num);
	}

	return endings;
}

int NumericEnding::getJumpCount() const {
	QList<int> numbers = getNumbers();
	int count = 0;

	for (int i = 0; i < numbers.size(); ++i) {
		if ((int)i + 1 != numbers[i]) {
			break;
		}

		count = i + 1;
	}

	return count;
}

///////////////////////////////////////////////////////////////////////////////
BarNumber::BarNumber() {
	index_ = 0;
	showOnParagraphStart_ = false;
	align_ = 0;
	showFlag_ = 1; // staff
	barRange_ = 1; // can't be 0
	prefix_ = QString();
}

void BarNumber::setIndex(int index) {
	index_ = index;
}

int BarNumber::getIndex() const {
	return index_;
}

void BarNumber::setShowOnParagraphStart(bool show) {
	showOnParagraphStart_ = show;
}

bool BarNumber::getShowOnParagraphStart() const {
	return showOnParagraphStart_;
}

void BarNumber::setAlign(int align)// 0:left, 1:center, 2:right
{
	align_ = align;
}

int BarNumber::getAlign() const {
	return align_;
}

void BarNumber::setShowFlag(int flag) {
	showFlag_ = flag;
}

int BarNumber::getShowFlag() const {
	return showFlag_;
}

void BarNumber::setShowEveryBarCount(int count) {
	barRange_ = count;
}

int BarNumber::getShowEveryBarCount() const {
	return barRange_;
}

void BarNumber::setPrefix(const QString& str) {
	prefix_ = str;
}

QString BarNumber::getPrefix() const {
	return prefix_;
}

///////////////////////////////////////////////////////////////////////////////
MidiController::MidiController() {
	midiType_ = Midi_Controller;
	controller_ = 64; // pedal
	value_ = 0;
}

void MidiController::setController(int number) {
	controller_ = number;
}

int MidiController::getController() const {
	return controller_;
}

void MidiController::setValue(int value) {
	value_ = value;
}

int MidiController::getValue() const {
	return value_;
}

///////////////////////////////////////////////////////////////////////////////
MidiProgramChange::MidiProgramChange() {
	midiType_ = Midi_Program_Change;
	patch_ = 0; // grand piano
}

void MidiProgramChange::setPatch(int patch) {
	patch_ = patch;
}

int MidiProgramChange::getPatch() const {
	return patch_;
}

///////////////////////////////////////////////////////////////////////////////
MidiChannelPressure::MidiChannelPressure() :
	pressure_(0) {
	midiType_ = Midi_Channel_Pressure;
}

void MidiChannelPressure::setPressure(int pressure) {
	pressure_ = pressure;
}

int MidiChannelPressure::getPressure() const {
	return pressure_;
}

///////////////////////////////////////////////////////////////////////////////
MidiPitchWheel::MidiPitchWheel() {
	midiType_ = Midi_Pitch_Wheel;
	value_ = 0;
}

void MidiPitchWheel::setValue(int value) {
	value_ = value;
}

int MidiPitchWheel::getValue() const {
	return value_;
}

///////////////////////////////////////////////////////////////////////////////
Measure::Measure(int index) {
	barNumber_ = new BarNumber();
	barNumber_->setIndex(index);
	time_ = new TimeSignature();

	clear();
}

Measure::~Measure(){
	clear();

	delete barNumber_;
	delete time_;
}

BarNumber* Measure::getBarNumber() const {
	return barNumber_;
}

TimeSignature* Measure::getTime() const {
	return time_;
}

void Measure::setLeftBarline(int barline) {
	leftBarline_ = (BarlineType) barline;
}

BarlineType Measure::getLeftBarline() const {
	return leftBarline_;
}

void Measure::setRightBarline(int barline) {
	rightBarline_ = (BarlineType) barline;
}

BarlineType Measure::getRightBarline() const {
	return rightBarline_;
}

void Measure::setBackwardRepeatCount(int repeatCount) {
	repeatCount_ = repeatCount;
}

int Measure::getBackwardRepeatCount() const {
	return repeatCount_;
}

void Measure::setTypeTempo(double tempo) {
	typeTempo_ = tempo;
}

double Measure::getTypeTempo() const {
	return typeTempo_;
}

void Measure::setIsPickup(bool pickup) {
	pickup_ = pickup;
}

bool Measure::getIsPickup() const {
	return pickup_;
}

void Measure::setIsMultiMeasureRest(bool rest) {
	multiMeasureRest_ = rest;
}

bool Measure::getIsMultiMeasureRest() const {
	return multiMeasureRest_;
}

void Measure::setMultiMeasureRestCount(int count) {
	multiMeasureRestCount_ = count;
}

int Measure::getMultiMeasureRestCount() const {
	return multiMeasureRestCount_;
}

void Measure::clear() {
	leftBarline_ = Barline_Default;
	rightBarline_ = Barline_Default;
	repeatCount_ = 1;
	typeTempo_ = 96.00;
	setLength(0x780); //time = 4/4
	pickup_ = false;
	multiMeasureRest_ = false;
	multiMeasureRestCount_ = 0;
}

///////////////////////////////////////////////////////////////////////////////
MeasureData::MeasureData() {
	key_ = new Key();
	clef_ = new Clef();
}

MeasureData::~MeasureData(){
	int i;
	for(i=0; i<musicDatas_.size(); ++i){
		delete musicDatas_[i];
	}
	musicDatas_.clear();

	// noteContainers_ also in musicDatas_, no need to destory
	noteContainers_.clear();

	// only delete at element start
	for(i=0; i<crossMeasureElements_.size(); ++i){
		if(crossMeasureElements_[i].second){
			delete crossMeasureElements_[i].first;
		}
	}
	crossMeasureElements_.clear();

	for(i=0; i<midiDatas_.size(); ++i){
		delete midiDatas_[i];
	}
	midiDatas_.clear();

	delete key_;
	delete clef_;
}

Key* MeasureData::getKey() const {
	return key_;
}

Clef* MeasureData::getClef() const {
	return clef_;
}

void MeasureData::addNoteContainer(NoteContainer* ptr) {
	noteContainers_.push_back(ptr);
}

QList<NoteContainer*> MeasureData::getNoteContainers() const {
	return noteContainers_;
}

void MeasureData::addMusicData(MusicData* ptr) {
	musicDatas_.push_back(ptr);
}

QList<MusicData*> MeasureData::getMusicDatas(MusicDataType type) {
	int i;
	QList<MusicData*> notations;

	for (i = 0; i < musicDatas_.size(); ++i) {
		if (type == MusicData_None || musicDatas_[i]->getMusicDataType() == type) {
			notations.push_back(musicDatas_[i]);
		}
	}

	return notations;
}

void MeasureData::addCrossMeasureElement(MusicData* ptr, bool start) {
	crossMeasureElements_.push_back(qMakePair(ptr, start));
}

QList<MusicData*> MeasureData::getCrossMeasureElements(
		MusicDataType type, PairType pairType)
{
	int i;
	QList<MusicData*> pairs;

	for (i = 0; i < crossMeasureElements_.size(); ++i) {
		if ((type == MusicData_None || crossMeasureElements_[i].first->getMusicDataType() == type)
				&& (pairType == PairType_All || ((crossMeasureElements_[i].second && pairType == PairType_Start)
						|| (!crossMeasureElements_[i].second && pairType == PairType_Stop)))) {
			pairs.push_back(crossMeasureElements_[i].first);
		}
	}

	return pairs;
}

void MeasureData::addMidiData(MidiData* ptr) {
	midiDatas_.push_back(ptr);
}

QList<MidiData*> MeasureData::getMidiDatas(MidiType type) {
	int i;
	QList<MidiData*> datas;

	for (i = 0; i < midiDatas_.size(); ++i) {
		if (type == Midi_None || midiDatas_[i]->getMidiType() == type) {
			datas.push_back(midiDatas_[i]);
		}
	}

	return datas;
}

//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
StreamHandle::StreamHandle() :
	size_(0), curPos_(0), point_(NULL) {
}

StreamHandle::StreamHandle(unsigned char* p, int size) :
	size_(size), curPos_(0), point_(p) {
}

StreamHandle::~StreamHandle() {
	point_ = NULL;
}

bool StreamHandle::read(char* buff, int size) {
	if (point_ != NULL && curPos_ + size <= size_) {
		memcpy(buff, point_ + curPos_, size);
		curPos_ += size;

		return true;
	}

	return false;
}

bool StreamHandle::write(char* /*buff*/, int /*size*/) {
	return true;
}

// Block.cpp
///////////////////////////////////////////////////////////////////////////////////////////////////
Block::Block() {
	doResize(0);
}

Block::Block(unsigned int count) {
	doResize(count);
}

Block::~Block() {
}

void Block::resize(unsigned int count) {
	doResize(count);
}

void Block::doResize(unsigned int count) {
	data_.clear();
	for(unsigned int i=0; i<count; ++i) {
		data_.push_back('\0');
	}
	//data_.resize(count);
}

const unsigned char* Block::data() const {
	//return const_cast<unsigned char*>(&data_.front());
	return &data_.front();
}

unsigned char* Block::data() {
	return &data_.front();
}

int Block::size() const {
	return data_.size();
}

bool Block::toBoolean() const {
	if (data() == NULL) {
		return false;
	}

	return size() == 1 && data()[0] == 0x01;
}

unsigned int Block::toUnsignedInt() const {
	if (data() == NULL) {
		return 0;
	}

	int num = 0;

	for (int i = 0; i < (int)sizeof(int) && i < size(); ++i) {
		num = (num << 8) + *(data() + i);
	}

	return num;
}

int Block::toInt() const {
	if (data() == NULL) {
		return 0;
	}

	int i;
	int num = 0;

	for (i = 0; i < (int)sizeof(int) && i < size(); ++i) {
		num = (num << 8) + (int) *(data() + i);
	}

	std::size_t minSize = sizeof(int);
	if (size() < (int)minSize) {
		minSize = size();
	}

	if ((*(data()) & 0x80) == 0x80) {
		int maxNum = int(pow(2.0, (int) minSize * 8));
		num -= maxNum;
		//num *= -1;
	}

	return num;
}

QByteArray Block::toStrByteArray() const {
	if (data() == NULL) {
		return QByteArray();
	}

	QByteArray arr((char*) data(), size());

	return arr;
}

QByteArray Block::fixedSizeBufferToStrByteArray() const {
	QByteArray str;

	for (int i = 0; i < size(); ++i) {
		if (*(data() + i) == '\0') {
			break;
		}

		str += (char) *(data() + i);
	}

	return str;
}

bool Block::operator ==(const Block& block) const {
	if (size() != block.size()) {
		return false;
	}

	for (int i = 0; i < size() && i < block.size(); ++i) {
		if (*(data() + i) != *(block.data() + i)) {
			return false;
		}
	}

	return true;
}

bool Block::operator !=(const Block& block) const {
	return !(*this == block);
}

///////////////////////////////////////////////////////////////////////////////////////////////////
FixedBlock::FixedBlock() :
	Block() {
}

FixedBlock::FixedBlock(unsigned int count) :
	Block(count) {
}

void FixedBlock::resize(unsigned int /*count*/) {
	//	Block::resize(size);
}

///////////////////////////////////////////////////////////////////////////////////////////////////
SizeBlock::SizeBlock() :
	FixedBlock(4) {
}

unsigned int SizeBlock::toSize() const {
	unsigned int i;
	unsigned int num(0);
	const unsigned int SIZE = 4;

	for (i = 0; i < SIZE; ++i) {
		num = (num << 8) + *(data() + i);
	}

	return num;
}

/*void SizeBlock::fromUnsignedInt(unsigned int count)
 {
 unsigned_int_to_char_buffer(count, data());
 }*/

///////////////////////////////////////////////////////////////////////////////////////////////////
NameBlock::NameBlock() :
	FixedBlock(4) {
}

/*void NameBlock::setValue(const char* const name)
 {
 unsigned int i;

 for( i=0; i<size() && *(name+i)!='\0'; ++i )
 {
 *(data()+i) = *(name+i);
 }
 }*/

bool NameBlock::isEqual(const QString& name) const {
	int nsize = name.size();

	if (nsize != size()) {
		return false;
	}

	for (int i = 0; i < size() && nsize; ++i) {
		if (data()[i] != name[i]) {
			return false;
		}
	}

	return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
CountBlock::CountBlock() :
	FixedBlock(2) {
}

/*void CountBlock::setValue(unsigned short count)
 {
 unsigned int i;
 unsigned int SIZE = sizeof(unsigned short);

 for( i=0; i<SIZE; ++i )
 {
 data()[SIZE-1-i] = count % 256;
 count /= 256;
 }
 }*/

unsigned short CountBlock::toCount() const {
	unsigned short num = 0;

	for (int i = 0; i < size() && i < (int)sizeof(unsigned short); ++i) {
		num = (num << 8) + *(data() + i);
	}

	return num;
}

// Chunk.cpp
const QString Chunk::TrackName	= "TRAK";
const QString Chunk::PageName	= "PAGE";
const QString Chunk::LineName	= "LINE";
const QString Chunk::StaffName	= "STAF";
const QString Chunk::MeasureName = "MEAS";
const QString Chunk::ConductName = "COND";
const QString Chunk::BdatName	= "BDAT";

Chunk::Chunk() {
}

NameBlock Chunk::getName() const {
	return nameBlock_;
}

////////////////////////////////////////////////////////////////////////////////
const unsigned int SizeChunk::version3TrackSize = 0x13a;

SizeChunk::SizeChunk() :
	Chunk() {
	sizeBlock_ = new SizeBlock();
	dataBlock_ = new Block();
}

SizeChunk::~SizeChunk() {
	delete sizeBlock_;
	delete dataBlock_;
}

SizeBlock* SizeChunk::getSizeBlock() const {
	return sizeBlock_;
}

Block* SizeChunk::getDataBlock() const {
	return dataBlock_;
}

/////////////////////////////////////////////////////////////////////////////////
GroupChunk::GroupChunk() : Chunk() {
	childCount_ = new CountBlock();
}

GroupChunk::~GroupChunk() {
	delete childCount_;
}

CountBlock* GroupChunk::getCountBlock() const {
	return childCount_;
}

// ChunkParse.cpp
unsigned int getHighNibble(unsigned int byte) {
	return byte / 16;
}

unsigned int getLowNibble(unsigned int byte) {
	return byte % 16;
}

int oveKeyToKey(int oveKey) {
	int key = 0;

	if( oveKey == 0 ) {
		key = 0;
	}
	else if( oveKey > 7 ) {
		key = oveKey - 7;
	}
	else if( oveKey <= 7 ) {
		key = oveKey * (-1);
	}

	return key;
}

///////////////////////////////////////////////////////////////////////////////
BasicParse::BasicParse(OveSong* ove) :
	ove_(ove), handle_(NULL), notify_(NULL) {
}

BasicParse::BasicParse() :
	ove_(NULL), handle_(NULL), notify_(NULL) {
}

BasicParse::~BasicParse() {
	ove_ = NULL;
	handle_ = NULL;
	notify_ = NULL;
}

void BasicParse::setNotify(IOveNotify* notify) {
	notify_ = notify;
}

bool BasicParse::parse() {
	return false;
}

bool BasicParse::readBuffer(Block& placeHolder, int size) {
	if (handle_ == NULL) {
		return false;
	}
	if (placeHolder.size() != size) {
		placeHolder.resize(size);
	}

	if (size > 0) {
		return handle_->read((char*) placeHolder.data(), placeHolder.size());
	}

	return true;
}

bool BasicParse::jump(int offset) {
	if (handle_ == NULL || offset < 0) {
		return false;
	}

	if (offset > 0) {
		Block placeHolder(offset);
		return handle_->read((char*) placeHolder.data(), placeHolder.size());
	}

	return true;
}

void BasicParse::messageOut(const QString& str) {
	if (notify_ != NULL) {
		notify_->loadInfo(str);
	}
}

///////////////////////////////////////////////////////////////////////////////
OvscParse::OvscParse(OveSong* ove) :
	BasicParse(ove), chunk_(NULL) {
}

OvscParse::~OvscParse() {
	chunk_ = NULL;
}

void OvscParse::setOvsc(SizeChunk* chunk) {
	chunk_ = chunk;
}

bool OvscParse::parse() {
	Block* dataBlock = chunk_->getDataBlock();
	unsigned int blockSize = chunk_->getSizeBlock()->toSize();
	StreamHandle handle(dataBlock->data(), blockSize);
	Block placeHolder;

	handle_ = &handle;

	// version
	if (!readBuffer(placeHolder, 1)) { return false; }
	bool version4 = placeHolder.toUnsignedInt() == 4;
	ove_->setIsVersion4(version4);

	QString str = QString("This file is created by Overture ") + (version4 ? "4" : "3") + "\n";
	messageOut(str);

	if( !jump(6) ) { return false; }

	// show page margin
	if (!readBuffer(placeHolder, 1)) { return false; }
	ove_->setShowPageMargin(placeHolder.toBoolean());

	if( !jump(1) ) { return false; }

	// transpose track
	if (!readBuffer(placeHolder, 1)) { return false; }
	ove_->setShowTransposeTrack(placeHolder.toBoolean());

	// play repeat
	if (!readBuffer(placeHolder, 1)) { return false; }
	ove_->setPlayRepeat(placeHolder.toBoolean());

	// play style
	if (!readBuffer(placeHolder, 1)) { return false; }
	OveSong::PlayStyle style = OveSong::Record;
	if(placeHolder.toUnsignedInt() == 1){
		style = OveSong::Swing;
	}
	else if(placeHolder.toUnsignedInt() == 2){
		style = OveSong::Notation;
	}
	ove_->setPlayStyle(style);

	// show line break
	if (!readBuffer(placeHolder, 1)) { return false; }
	ove_->setShowLineBreak(placeHolder.toBoolean());

	// show ruler
	if (!readBuffer(placeHolder, 1)) { return false; }
	ove_->setShowRuler(placeHolder.toBoolean());

	// show color
	if (!readBuffer(placeHolder, 1)) { return false; }
	ove_->setShowColor(placeHolder.toBoolean());

	return true;
}

///////////////////////////////////////////////////////////////////////////////
TrackParse::TrackParse(OveSong* ove)
:BasicParse(ove) {
}

TrackParse::~TrackParse() {
}

void TrackParse::setTrack(SizeChunk* chunk) {
	chunk_ = chunk;
}

bool TrackParse::parse() {
	Block* dataBlock = chunk_->getDataBlock();
	unsigned int blockSize = ove_->getIsVersion4() ? chunk_->getSizeBlock()->toSize() : SizeChunk::version3TrackSize;
	StreamHandle handle(dataBlock->data(), blockSize);
	Block placeHolder;

	handle_ = &handle;

	Track* oveTrack = new Track();
	ove_->addTrack(oveTrack);

	// 2 32bytes long track name buffer
	if( !readBuffer(placeHolder, 32) ) { return false; }
	oveTrack->setName(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

	if( !readBuffer(placeHolder, 32) ) { return false; }
	oveTrack->setBriefName(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

	if( !jump(8) ) { return false; } //0x fffa0012 fffa0012
	if( !jump(1) ) { return false; }

	// patch
	if( !readBuffer(placeHolder, 1) ) { return false; }
	unsigned int thisByte = placeHolder.toInt();
	oveTrack->setPatch(thisByte&0x7f);

	// show name
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowName(placeHolder.toBoolean());

	// show brief name
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowBriefName(placeHolder.toBoolean());

	if( !jump(1) ) { return false; }

	// show transpose
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowTranspose(placeHolder.toBoolean());

	if( !jump(1) ) { return false; }

	// mute
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setMute(placeHolder.toBoolean());

	// solo
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setSolo(placeHolder.toBoolean());

	if( !jump(1) ) { return false; }

	// show key each line
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowKeyEachLine(placeHolder.toBoolean());

	// voice count
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setVoiceCount(placeHolder.toUnsignedInt());

	if( !jump(3) ) { return false; }

	// transpose value [-127, 127]
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setTranspose(placeHolder.toInt());

	if( !jump(2) ) { return false; }

	// start clef
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setStartClef(placeHolder.toUnsignedInt());

	// transpose celf
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setTransposeClef(placeHolder.toUnsignedInt());

	// start key
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setStartKey(placeHolder.toUnsignedInt());

	// display percent
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setDisplayPercent(placeHolder.toUnsignedInt());

	// show leger line
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowLegerLine(placeHolder.toBoolean());

	// show clef
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowClef(placeHolder.toBoolean());

	// show time signature
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowTimeSignature(placeHolder.toBoolean());

	// show key signature
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowKeySignature(placeHolder.toBoolean());

	// show barline
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowBarline(placeHolder.toBoolean());

	// fill with rest
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setFillWithRest(placeHolder.toBoolean());

	// flat tail
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setFlatTail(placeHolder.toBoolean());

	// show clef each line
	if( !readBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setShowClefEachLine(placeHolder.toBoolean());

	if( !jump(12) ) { return false; }

	// 8 voices
	int i;
	QList<Voice*> voices;
	for( i=0; i<8; ++i ) {
		Voice* voice = new Voice();

		if( !jump(5) ) { return false; }

		// channel
		if( !readBuffer(placeHolder, 1) ) { return false; }
		voice->setChannel(placeHolder.toUnsignedInt());

		// volume
		if( !readBuffer(placeHolder, 1) ) { return false; }
		voice->setVolume(placeHolder.toInt());

		// pitch shift
		if( !readBuffer(placeHolder, 1) ) { return false; }
		voice->setPitchShift(placeHolder.toInt());

		// pan
		if( !readBuffer(placeHolder, 1) ) { return false; }
                voice->setPan(placeHolder.toInt() + 64);

		if( !jump(6) ) { return false; }

		// patch
		if( !readBuffer(placeHolder, 1) ) { return false; }
		voice->setPatch(placeHolder.toInt());

		voices.push_back(voice);
	}

	// stem type
	for( i=0; i<8; ++i ) {
		if( !readBuffer(placeHolder, 1) ) { return false; }
		voices[i]->setStemType(placeHolder.toUnsignedInt());

		oveTrack->addVoice(voices[i]);
	}

	// percussion define
	QList<Track::DrumNode> nodes;
	for(i=0; i<16; ++i) {
		nodes.push_back(Track::DrumNode());
	}

	// line
	for( i=0; i<16; ++i ) {
		if( !readBuffer(placeHolder, 1) ) { return false; }
		nodes[i].line_ = placeHolder.toInt();
	}

	// head type
	for( i=0; i<16; ++i ) {
		if( !readBuffer(placeHolder, 1) ) { return false; }
		nodes[i].headType_ = placeHolder.toUnsignedInt();
	}

	// pitch
	for( i=0; i<16; ++i ) {
		if( !readBuffer(placeHolder, 1) ) { return false; }
		nodes[i].pitch_ = placeHolder.toUnsignedInt();
	}

	// voice
	for( i=0; i<16; ++i ) {
		if( !readBuffer(placeHolder, 1) ) { return false; }
		nodes[i].voice_ = placeHolder.toUnsignedInt();
	}

	for( i=0; i<nodes.size(); ++i ) {
		oveTrack->addDrum(nodes[i]);
	}

/*	if( !Jump(17) ) { return false; }

	// voice 0 channel
	if( !ReadBuffer(placeHolder, 1) ) { return false; }
	oveTrack->setChannel(placeHolder.toUnsignedInt());

	// to be continued. if anything important...*/

	return true;
}

///////////////////////////////////////////////////////////////////////////////
GroupParse::GroupParse(OveSong* ove)
:BasicParse(ove) {
}

GroupParse::~GroupParse(){
	sizeChunks_.clear();
}

void GroupParse::addSizeChunk(SizeChunk* sizeChunk) {
	sizeChunks_.push_back(sizeChunk);
}

bool GroupParse::parse() {
	return false;
}

///////////////////////////////////////////////////////////////////////////////
PageGroupParse::PageGroupParse(OveSong* ove)
:BasicParse(ove) {
}

PageGroupParse::~PageGroupParse(){
	pageChunks_.clear();
}

void PageGroupParse::addPage(SizeChunk* chunk) {
	pageChunks_.push_back(chunk);
}

bool PageGroupParse::parse() {
    if( pageChunks_.isEmpty() ) {
	    return false;
	}

	int i;
	for( i=0; i<pageChunks_.size(); ++i ) {
		Page* page = new Page();
		ove_->addPage(page);

		if( !parsePage(pageChunks_[i], page) ) { return false; }
	}

	return true;
}

bool PageGroupParse::parsePage(SizeChunk* chunk, Page* page) {
	Block placeHolder(2);
	StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize());

	handle_ = &handle;

	// begin line
	if( !readBuffer(placeHolder, 2) ) { return false; }
	page->setBeginLine(placeHolder.toUnsignedInt());

	// line count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	page->setLineCount(placeHolder.toUnsignedInt());

	if( !jump(4) ) { return false; }

	// staff interval
	if( !readBuffer(placeHolder, 2) ) { return false; }
	page->setStaffInterval(placeHolder.toUnsignedInt());

	// line interval
	if( !readBuffer(placeHolder, 2) ) { return false; }
	page->setLineInterval(placeHolder.toUnsignedInt());

	// staff inline interval
	if( !readBuffer(placeHolder, 2) ) { return false; }
	page->setStaffInlineInterval(placeHolder.toUnsignedInt());

	// line bar count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	page->setLineBarCount(placeHolder.toUnsignedInt());

	// page line count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	page->setPageLineCount(placeHolder.toUnsignedInt());

	// left margin
	if( !readBuffer(placeHolder, 4) ) { return false; }
	page->setLeftMargin(placeHolder.toUnsignedInt());

	// top margin
	if( !readBuffer(placeHolder, 4) ) { return false; }
	page->setTopMargin(placeHolder.toUnsignedInt());

	// right margin
	if( !readBuffer(placeHolder, 4) ) { return false; }
	page->setRightMargin(placeHolder.toUnsignedInt());

	// bottom margin
	if( !readBuffer(placeHolder, 4) ) { return false; }
	page->setBottomMargin(placeHolder.toUnsignedInt());

	// page width
	if( !readBuffer(placeHolder, 4) ) { return false; }
	page->setPageWidth(placeHolder.toUnsignedInt());

	// page height
	if( !readBuffer(placeHolder, 4) ) { return false; }
	page->setPageHeight(placeHolder.toUnsignedInt());

	handle_ = NULL;

	return true;
}

///////////////////////////////////////////////////////////////////////////////
StaffCountGetter::StaffCountGetter(OveSong* ove)
:BasicParse(ove) {
}

unsigned int StaffCountGetter::getStaffCount(SizeChunk* chunk) {
	StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize());
	Block placeHolder;

	handle_ = &handle;

	if( !jump(6) ) { return false; }

	// staff count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	return placeHolder.toUnsignedInt();
}

///////////////////////////////////////////////////////////////////////////////
LineGroupParse::LineGroupParse(OveSong* ove) :
	BasicParse(ove), chunk_(NULL) {
}

LineGroupParse::~LineGroupParse(){
	chunk_ = NULL;
	lineChunks_.clear();
	staffChunks_.clear();
}

void LineGroupParse::setLineGroup(GroupChunk* chunk) {
	chunk_ = chunk;
}

void LineGroupParse::addLine(SizeChunk* chunk) {
	lineChunks_.push_back(chunk);
}

void LineGroupParse::addStaff(SizeChunk* chunk) {
	staffChunks_.push_back(chunk);
}

bool LineGroupParse::parse() {
    if( lineChunks_.isEmpty() || staffChunks_.size() % lineChunks_.size() != 0 ) { return false; }

	int i;
	unsigned int j;
	unsigned int lineStaffCount = staffChunks_.size() / lineChunks_.size();

	for( i=0; i<lineChunks_.size(); ++i ) {
		Line* line = new Line();

		ove_->addLine(line);

		if( !parseLine(lineChunks_[i], line) ) { return false; }

		for( j=lineStaffCount*i; j<lineStaffCount*(i+1); ++j ) {
			Staff* staffPtr = new Staff();

			line->addStaff(staffPtr);

			if( !parseStaff(staffChunks_[j], staffPtr) ) { return false; }
		}
	}

	return true;
}

bool LineGroupParse::parseLine(SizeChunk* chunk, Line* line) {
	Block placeHolder;

	StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize());

	handle_ = &handle;

	if( !jump(2) ) { return false; }

	// begin bar
	if( !readBuffer(placeHolder, 2) ) { return false; }
	line->setBeginBar(placeHolder.toUnsignedInt());

	// bar count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	line->setBarCount(placeHolder.toUnsignedInt());

	if( !jump(6) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	line->setYOffset(placeHolder.toInt());

	// left x offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	line->setLeftXOffset(placeHolder.toInt());

	// right x offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	line->setRightXOffset(placeHolder.toInt());

	if( !jump(4) ) { return false; }

	handle_ = NULL;

	return true;
}

bool LineGroupParse::parseStaff(SizeChunk* chunk, Staff* staff) {
	Block placeHolder;

	StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize());

	handle_ = &handle;

	if( !jump(7) ) { return false; }

	// clef
	if( !readBuffer(placeHolder, 1) ) { return false; }
	staff->setClefType(placeHolder.toUnsignedInt());

	// key
	if( !readBuffer(placeHolder, 1) ) { return false; }
	staff->setKeyType(oveKeyToKey(placeHolder.toUnsignedInt()));

	if( !jump(2) ) { return false; }

	// visible
	if( !readBuffer(placeHolder, 1) ) { return false; }
	staff->setVisible(placeHolder.toBoolean());

	if( !jump(12) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	staff->setYOffset(placeHolder.toInt());

	int jumpAmount = ove_->getIsVersion4() ? 26 : 18;
	if( !jump(jumpAmount) ) { return false; }

	// group type
	if( !readBuffer(placeHolder, 1) ) { return false; }
	GroupType groupType = Group_None;
	if(placeHolder.toUnsignedInt() == 1) {
		groupType = Group_Brace;
	} else if(placeHolder.toUnsignedInt() == 2) {
		groupType = Group_Bracket;
	}
	staff->setGroupType(groupType);

	// group staff count
	if( !readBuffer(placeHolder, 1) ) { return false; }
	staff->setGroupStaffCount(placeHolder.toUnsignedInt());

	handle_ = NULL;

	return true;
}

///////////////////////////////////////////////////////////////////////////////
BarsParse::BarsParse(OveSong* ove) :
	BasicParse(ove) {
}

BarsParse::~BarsParse(){
	measureChunks_.clear();
	conductChunks_.clear();
	bdatChunks_.clear();
}

void BarsParse::addMeasure(SizeChunk* chunk) {
	measureChunks_.push_back(chunk);
}

void BarsParse::addConduct(SizeChunk* chunk) {
	conductChunks_.push_back(chunk);
}

void BarsParse::addBdat(SizeChunk* chunk) {
	bdatChunks_.push_back(chunk);
}

bool BarsParse::parse() {
	int i;
	int trackMeasureCount = ove_->getTrackBarCount();
	int trackCount = ove_->getTrackCount();
	int measureDataCount = trackCount * measureChunks_.size();
	QList<Measure*> measures;
	QList<MeasureData*> measureDatas;

    if( measureChunks_.isEmpty() ||
		measureChunks_.size() != conductChunks_.size() ||
		(int)bdatChunks_.size() != measureDataCount ) {
		return false;
	}

	// add to ove
	for ( i=0; i<(int)measureChunks_.size(); ++i ) {
		Measure* measure = new Measure(i);

		measures.push_back(measure);
		ove_->addMeasure(measure);
	}

	for ( i=0; i<measureDataCount; ++i ) {
		MeasureData* oveMeasureData = new MeasureData();

		measureDatas.push_back(oveMeasureData);
		ove_->addMeasureData(oveMeasureData);
	}

	for( i=0; i<(int)measureChunks_.size(); ++i ) {
		Measure* measure = measures[i];

		// MEAS
		if( !parseMeas(measure, measureChunks_[i]) ) {
			QString ss = "failed in parse MEAS " + i + '\n';
			messageOut(ss);

			return false;
		}
	}

	for( i=0; i<(int)conductChunks_.size(); ++i ) {
		// COND
		if( !parseCond(measures[i], measureDatas[i], conductChunks_[i]) ) {
			QString ss = "failed in parse COND " + i + '\n';
			messageOut(ss);

			return false;
		}
	}

	for( i=0; i<(int)bdatChunks_.size(); ++i ) {
		int measId = i % trackMeasureCount;

		// BDAT
		if( !parseBdat(measures[measId], measureDatas[i], bdatChunks_[i]) ) {
			QString ss = "failed in parse BDAT " + i + '\n';
			messageOut(ss);

			return false;
		}

		if( notify_ != NULL ) {
			int measureID = i % trackMeasureCount;
			int trackID = i / trackMeasureCount;

			//msg.msg_ = OVE_IMPORT_POS;
			//msg.param1_ = (measureID<<16) + trackMeasureCount;
			//msg.param2_ = (trackID<<16) + trackCount;

			notify_->loadPosition(measureID, trackMeasureCount, trackID, trackCount);
		}
	}

	return true;
}

bool BarsParse::parseMeas(Measure* measure, SizeChunk* chunk) {
	Block placeHolder;

	StreamHandle measureHandle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize());

	handle_ = &measureHandle;

	if( !jump(2) ) { return false; }

	// multi-measure rest
	if( !readBuffer(placeHolder, 1) ) { return false; }
	measure->setIsMultiMeasureRest(placeHolder.toBoolean());

	// pickup
	if( !readBuffer(placeHolder, 1) ) { return false; }
	measure->setIsPickup(placeHolder.toBoolean());

	if( !jump(4) ) { return false; }

	// left barline
	if( !readBuffer(placeHolder, 1) ) { return false; }
	measure->setLeftBarline(placeHolder.toUnsignedInt());

	// right barline
	if( !readBuffer(placeHolder, 1) ) { return false; }
	measure->setRightBarline(placeHolder.toUnsignedInt());

	// tempo
	if( !readBuffer(placeHolder, 2) ) { return false; }
	double tempo = ((double)placeHolder.toUnsignedInt());
	if( ove_->getIsVersion4() ) {
		tempo /= 100.0;
	}
	measure->setTypeTempo(tempo);

	// bar length(tick)
	if( !readBuffer(placeHolder, 2) ) { return false; }
	measure->setLength(placeHolder.toUnsignedInt());

	if( !jump(6) ) { return false; }

	// bar number offset
	if( !parseOffsetElement(measure->getBarNumber()) ) { return false; }

	if( !jump(2) ) { return false; }

	// multi-measure rest count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	measure->setMultiMeasureRestCount(placeHolder.toUnsignedInt());

	handle_ = NULL;

	return true;
}

bool BarsParse::parseCond(Measure* measure, MeasureData* measureData, SizeChunk* chunk) {
	Block placeHolder;

	StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize());

	handle_ = &handle;

	// item count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	unsigned int cnt = placeHolder.toUnsignedInt();

	if( !parseTimeSignature(measure, 36) ) { return false; }

	for( unsigned int i=0; i<cnt; ++i ) {
		if( !readBuffer(placeHolder, 2) ) { return false; }
		unsigned int twoByte = placeHolder.toUnsignedInt();
		unsigned int oldBlockSize = twoByte - 11;
		unsigned int newBlockSize = twoByte - 7;

		// type id
		if( !readBuffer(placeHolder, 1) ) { return false; }
		unsigned int thisByte = placeHolder.toUnsignedInt();
		CondType type;

		if( !getCondElementType(thisByte, type) ) { return false; }

		switch (type) {
		case Cond_Bar_Number: {
			if (!parseBarNumber(measure, twoByte - 1)) {
				return false;
			}
			break;
		}
		case Cond_Repeat: {
			if (!parseRepeatSymbol(measureData, oldBlockSize)) {
				return false;
			}
			break;
		}
		case Cond_Numeric_Ending: {
			if (!parseNumericEndings(measureData, oldBlockSize)) {
				return false;
			}
			break;
		}
		case Cond_Decorator: {
			if (!parseDecorators(measureData, newBlockSize)) {
				return false;
			}
			break;
		}
		case Cond_Tempo: {
			if (!parseTempo(measureData, newBlockSize)) {
				return false;
			}
			break;
		}
		case Cond_Text: {
			if (!parseText(measureData, newBlockSize)) {
				return false;
			}
			break;
		}
		case Cond_Expression: {
			if (!parseExpressions(measureData, newBlockSize)) {
				return false;
			}
			break;
		}
		case Cond_Time_Parameters: {
			if (!parseTimeSignatureParameters(measure, newBlockSize)) {
				return false;
			}
			break;
		}
		case Cond_Barline_Parameters: {
			if (!parseBarlineParameters(measure, newBlockSize)) {
				return false;
			}
			break;
		}
		default: {
			if (!jump(newBlockSize)) {
				return false;
			}
			break;
		}
		}
	}

	handle_ = NULL;

	return true;
}

bool BarsParse::parseTimeSignature(Measure* measure, int /*length*/) {
	Block placeHolder;

	TimeSignature* timeSignature = measure->getTime();

	// numerator
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setNumerator(placeHolder.toUnsignedInt());

	// denominator
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setDenominator(placeHolder.toUnsignedInt());

	if( !jump(2) ) { return false; }

	// beat length
	if( !readBuffer(placeHolder, 2) ) { return false; }
	timeSignature->setBeatLength(placeHolder.toUnsignedInt());

	// bar length
	if( !readBuffer(placeHolder, 2) ) { return false; }
	timeSignature->setBarLength(placeHolder.toUnsignedInt());

	if( !jump(4) ) { return false; }

	// is symbol
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setIsSymbol(placeHolder.toBoolean());

	if( !jump(1) ) { return false; }

	// replace font
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setReplaceFont(placeHolder.toBoolean());

	// color
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setColor(placeHolder.toUnsignedInt());

	// show
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setShow(placeHolder.toBoolean());

	// show beat group
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setShowBeatGroup(placeHolder.toBoolean());

	if( !jump(6) ) { return false; }

	// numerator 1, 2, 3
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setGroupNumerator1(placeHolder.toUnsignedInt());
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setGroupNumerator2(placeHolder.toUnsignedInt());
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setGroupNumerator3(placeHolder.toUnsignedInt());

	// denominator
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setGroupDenominator1(placeHolder.toUnsignedInt());
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setGroupDenominator2(placeHolder.toUnsignedInt());
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setGroupDenominator3(placeHolder.toUnsignedInt());

	// beam group 1~4
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setBeamGroup1(placeHolder.toUnsignedInt());
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setBeamGroup2(placeHolder.toUnsignedInt());
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setBeamGroup3(placeHolder.toUnsignedInt());
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->setBeamGroup4(placeHolder.toUnsignedInt());

	// beam 16th
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->set16thBeamCount(placeHolder.toUnsignedInt());

	// beam 32th
	if( !readBuffer(placeHolder, 1) ) { return false; }
	timeSignature->set32thBeamCount(placeHolder.toUnsignedInt());

	return true;
}

bool BarsParse::parseTimeSignatureParameters(Measure* measure, int length) {
	Block placeHolder;
	TimeSignature* ts = measure->getTime();

	int cursor = ove_->getIsVersion4() ? 10 : 8;
	if( !jump(cursor) ) { return false; }

	// numerator
	if( !readBuffer(placeHolder, 1) ) { return false; }
	unsigned int numerator = placeHolder.toUnsignedInt();

	cursor = ove_->getIsVersion4() ? 11 : 9;
	if( ( length - cursor ) % 8 != 0 || (length - cursor) / 8 != (int)numerator ) {
		return false;
	}

	for( unsigned int i =0; i<numerator; ++i ) {
		// beat start unit
		if( !readBuffer(placeHolder, 2) ) { return false; }
		int beatStart = placeHolder.toUnsignedInt();

		// beat length unit
		if( !readBuffer(placeHolder, 2) ) { return false; }
		int beatLength = placeHolder.toUnsignedInt();

		if( !jump(2) ) { return false; }

		// beat start tick
		if( !readBuffer(placeHolder, 2) ) { return false; }
		int beatStartTick = placeHolder.toUnsignedInt();

		ts->addBeat(beatStart, beatLength, beatStartTick);
	}

	ts->endAddBeat();

	return true;
}

bool BarsParse::parseBarlineParameters(Measure* measure, int /*length*/) {
	Block placeHolder;

	int cursor = ove_->getIsVersion4() ? 12 : 10;
	if( !jump(cursor) ) { return false; }

	// repeat count
	if( !readBuffer(placeHolder, 1) ) { return false; }
	int repeatCount = placeHolder.toUnsignedInt();

	measure->setBackwardRepeatCount(repeatCount);

	if( !jump(6) ) { return false; }

	return true;
}

bool BarsParse::parseNumericEndings(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	NumericEnding* numeric = new NumericEnding();
	measureData->addCrossMeasureElement(numeric, true);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(numeric) ) { return false; }

	if( !jump(6) ) { return false; }

	// measure count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	//int offsetMeasure = placeHolder.toUnsignedInt() - 1;
	int offsetMeasure = placeHolder.toUnsignedInt();
	numeric->stop()->setMeasure(offsetMeasure);

	if( !jump(2) ) { return false; }

	// left x offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	numeric->getLeftShoulder()->setXOffset(placeHolder.toInt());

	// height
	if( !readBuffer(placeHolder, 2) ) { return false; }
	numeric->setHeight(placeHolder.toUnsignedInt());

	// left x offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	numeric->getRightShoulder()->setXOffset(placeHolder.toInt());

	if( !jump(2) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	numeric->getLeftShoulder()->setYOffset(placeHolder.toInt());
	numeric->getRightShoulder()->setYOffset(placeHolder.toInt());

	// number offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	numeric->getNumericHandle()->setXOffset(placeHolder.toInt());
	if( !readBuffer(placeHolder, 2) ) { return false; }
	numeric->getNumericHandle()->setYOffset(placeHolder.toInt());

	if( !jump(6) ) { return false; }

	// text size
	if( !readBuffer(placeHolder, 1) ) { return false; }
	unsigned int size = placeHolder.toUnsignedInt();

	// text : size maybe a huge value
	if( !readBuffer(placeHolder, size) ) { return false; }
	numeric->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

	// fix for wedding march.ove
	if( size % 2 == 0 ) {
		if( !jump(1) ) { return false; }
	}

	return true;
}

bool BarsParse::parseTempo(MeasureData* measureData, int /*length*/) {
	Block placeHolder;
	unsigned int thisByte;

	Tempo* tempo = new Tempo();
	measureData->addMusicData(tempo);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(tempo) ) { return false; }

	if( !readBuffer(placeHolder, 1) ) { return false; }
	thisByte = placeHolder.toUnsignedInt();

	// show tempo
	tempo->setShowMark( (getHighNibble(thisByte) & 0x4) == 0x4 );
	// show before text
	tempo->setShowBeforeText( (getHighNibble(thisByte) & 0x8 ) == 0x8 ) ;
	// show parenthesis
	tempo->setShowParenthesis( (getHighNibble(thisByte) & 0x1 ) == 0x1 );
	// left note type
	tempo->setLeftNoteType( getLowNibble(thisByte) );

	if( !jump(1) ) { return false; }

	if( ove_->getIsVersion4() ) {
		if( !jump(2) ) { return false; }

		// tempo
		if( !readBuffer(placeHolder, 2) ) { return false; }
		tempo->setTypeTempo(placeHolder.toUnsignedInt()/100);
	} else {
		// tempo
		if( !readBuffer(placeHolder, 2) ) { return false; }
		tempo->setTypeTempo(placeHolder.toUnsignedInt());

		if( !jump(2) ) { return false; }
	}

	// offset
	if( !parseOffsetElement(tempo) ) { return false; }

	if( !jump(16) ) { return false; }

	// 31 bytes left text
	if( !readBuffer(placeHolder, 31) ) { return false; }
	tempo->setLeftText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

	if( !readBuffer(placeHolder, 1) ) { return false; }
	thisByte = placeHolder.toUnsignedInt();

	// swing eighth
	tempo->setSwingEighth(getHighNibble(thisByte)!=8);

	// right note type
	tempo->setRightNoteType(getLowNibble(thisByte));

	// right text
	if( ove_->getIsVersion4() ) {
		if( !readBuffer(placeHolder, 31) ) { return false; }
		tempo->setRightText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

		if( !jump(1) ) { return false; }
	}

	return true;
}

bool BarsParse::parseBarNumber(Measure* measure, int /*length*/) {
	Block placeHolder;

	BarNumber* barNumber = measure->getBarNumber();

	if( !jump(2) ) { return false; }

	// show on paragraph start
	if( !readBuffer(placeHolder, 1) ) { return false; }
	barNumber->setShowOnParagraphStart(getLowNibble(placeHolder.toUnsignedInt())==8);

	unsigned int blankSize = ove_->getIsVersion4() ? 9 : 7;
	if( !jump(blankSize) ) { return false; }

	// text align
	if( !readBuffer(placeHolder, 1) ) { return false; }
	barNumber->setAlign(placeHolder.toUnsignedInt());

	if( !jump(4) ) { return false; }

	// show flag
	if( !readBuffer(placeHolder, 1) ) { return false; }
	barNumber->setShowFlag(placeHolder.toUnsignedInt());

	if( !jump(10) ) { return false; }

	// bar range
	if( !readBuffer(placeHolder, 1) ) { return false; }
	barNumber->setShowEveryBarCount(placeHolder.toUnsignedInt());

	// prefix
	if( !readBuffer(placeHolder, 2) ) { return false; }
	barNumber->setPrefix(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

	if( !jump(18) ) { return false; }

	return true;
}

bool BarsParse::parseText(MeasureData* measureData, int length) {
	Block placeHolder;

	Text* text = new Text();
	measureData->addMusicData(text);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(text) ) { return false; }

	// type
	if( !readBuffer(placeHolder, 1) ) { return false; }
	unsigned int thisByte = placeHolder.toUnsignedInt();
	bool includeLineBreak = ( (getHighNibble(thisByte)&0x2) != 0x2 );
	unsigned int id = getLowNibble(thisByte);
	Text::TextType textType = Text::Text_Rehearsal;

	if (id == 0) {
		textType = Text::Text_MeasureText;
	} else if (id == 1) {
		textType = Text::Text_SystemText;
	} else // id ==2
	{
		textType = Text::Text_Rehearsal;
	}

	text->setTextType(textType);

	if( !jump(1) ) { return false; }

	// x offset
	if( !readBuffer(placeHolder, 4) ) { return false; }
	text->setXOffset(placeHolder.toInt());

	// y offset
	if( !readBuffer(placeHolder, 4) ) { return false; }
	text->setYOffset(placeHolder.toInt());

	// width
	if( !readBuffer(placeHolder, 4) ) { return false; }
	text->setWidth(placeHolder.toUnsignedInt());

	// height
	if( !readBuffer(placeHolder, 4) ) { return false; }
	text->setHeight(placeHolder.toUnsignedInt());

	if( !jump(7) ) { return false; }

	// horizontal margin
	if( !readBuffer(placeHolder, 1) ) { return false; }
	text->setHorizontalMargin(placeHolder.toUnsignedInt());

	if( !jump(1) ) { return false; }

	// vertical margin
	if( !readBuffer(placeHolder, 1) ) { return false; }
	text->setVerticalMargin(placeHolder.toUnsignedInt());

	if( !jump(1) ) { return false; }

	// line thick
	if( !readBuffer(placeHolder, 1) ) { return false; }
	text->setLineThick(placeHolder.toUnsignedInt());

	if( !jump(2) ) { return false; }

	// text size
	if( !readBuffer(placeHolder, 2) ) { return false; }
	unsigned int size = placeHolder.toUnsignedInt();

	// text string, maybe huge
	if( !readBuffer(placeHolder, size) ) { return false; }
	text->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

	if( !includeLineBreak ) {
		if( !jump(6) ) { return false; }
	} else {
		unsigned int cursor = ove_->getIsVersion4() ? 43 : 41;
		cursor += size;

		// multi lines of text
		for( unsigned int i=0; i<2; ++i ) {
			if( (int)cursor < length ) {
				// line parameters count
				if( !readBuffer(placeHolder, 2) ) { return false; }
				unsigned int lineCount = placeHolder.toUnsignedInt();

				if( i==0 && int(cursor + 2 + 8*lineCount) > length ) {
					return false;
				}

				if( i==1 && int(cursor + 2 + 8*lineCount) != length ) {
					return false;
				}

				if( !jump(8*lineCount) ) { return false; }

				cursor += 2 + 8*lineCount;
			}
		}
	}

	return true;
}

bool BarsParse::parseRepeatSymbol(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	RepeatSymbol* repeat = new RepeatSymbol();
	measureData->addMusicData(repeat);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(repeat) ) { return false; }

	// RepeatType
	if( !readBuffer(placeHolder, 1) ) { return false; }
	repeat->setRepeatType(placeHolder.toUnsignedInt());

	if( !jump(13) ) { return false; }

	// offset
	if( !parseOffsetElement(repeat) ) { return false; }

	if( !jump(15) ) { return false; }

	// size
	if( !readBuffer(placeHolder, 2) ) { return false; }
	unsigned int size = placeHolder.toUnsignedInt();

	// text, maybe huge
	if( !readBuffer(placeHolder, size) ) { return false; }
	repeat->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

	// last 0
	if( size % 2 == 0 ) {
		if( !jump(1) ) { return false; }
	}

	return true;
}

bool BarsParse::parseBdat(Measure* /*measure*/, MeasureData* measureData, SizeChunk* chunk) {
	Block placeHolder;
	StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize());

	handle_ = &handle;

	// parse here
	if( !readBuffer(placeHolder, 2) ) { return false; }
	unsigned int cnt = placeHolder.toUnsignedInt();

	for( unsigned int i=0; i<cnt; ++i ) {
		// 0x0028 or 0x0016 or 0x002C
		if( !readBuffer(placeHolder, 2) ) { return false; }
		unsigned int count = placeHolder.toUnsignedInt() - 7;

		// type id
		if( !readBuffer(placeHolder, 1) ) { return false; }
		unsigned int thisByte = placeHolder.toUnsignedInt();
		BdatType type;

		if( !getBdatElementType(thisByte, type) ) { return false; }

		switch( type ) {
		case Bdat_Raw_Note :
		case Bdat_Rest :
		case Bdat_Note : {
				if( !parseNoteRest(measureData, count, type) ) { return false; }
				break;
			}
		case Bdat_Beam : {
				if( !parseBeam(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Harmony : {
				if( !parseHarmony(measureData, count) ) { return false; }
				break;
			}
		case Bdat_Clef : {
				if( !parseClef(measureData, count) ) { return false; }
				break;
			}
		case Bdat_Dynamics : {
				if( !parseDynamics(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Wedge : {
				if( !parseWedge(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Glissando : {
				if( !parseGlissando(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Decorator : {
				if( !parseDecorators(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Key : {
				if( !parseKey(measureData, count) ) { return false; }
				break;
			}
		case Bdat_Lyric : {
				if( !parseLyric(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Octave_Shift: {
				if( !parseOctaveShift(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Slur : {
				if( !parseSlur(measureData, count) ) { return false; }
				break;
			}
		case Bdat_Text : {
				if( !parseText(measureData, count) ) { return false; }
				break;
			}
		case Bdat_Tie : {
				if( !parseTie(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Tuplet : {
				if( !parseTuplet(measureData, count) ) { return false; }
				break;
			}
		case Bdat_Guitar_Bend :
		case Bdat_Guitar_Barre : {
				if( !parseSizeBlock(count) ) { return false; }
				break;
			}
		case Bdat_Pedal: {
				if( !parsePedal(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_KuoHao: {
				if( !parseKuohao(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Expressions: {
				if( !parseExpressions(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Harp_Pedal: {
				if( !parseHarpPedal(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Multi_Measure_Rest: {
				if( !parseMultiMeasureRest(measureData, count) ) { return false; }
				break;
			}
		case Bdat_Harmony_GuitarFrame: {
				if( !parseHarmonyGuitarFrame(measureData, count) ) { return false; }
				break;
			}
		case Bdat_Graphics_40:
		case Bdat_Graphics_RoundRect:
		case Bdat_Graphics_Rect:
		case Bdat_Graphics_Round:
		case Bdat_Graphics_Line:
		case Bdat_Graphics_Curve:
		case Bdat_Graphics_WedgeSymbol: {
				if( !parseSizeBlock(count) ) { return false; }
				break;
			}
		case Bdat_Midi_Controller : {
				if( !parseMidiController(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Midi_Program_Change : {
				if( !parseMidiProgramChange(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Midi_Channel_Pressure : {
				if( !parseMidiChannelPressure(measureData, count) ) { return false; }
			    break;
			}
		case Bdat_Midi_Pitch_Wheel : {
				if( !parseMidiPitchWheel(measureData, count) ) { return false; }
			    break;
			}
		default: {
				if( !jump(count) ) { return false; }
			    break;
			}
		}

		// if i==count-1 then is bar end place holder
	}

	handle_ = NULL;

	return true;
}

int getInt(int byte, int bits) {
	int num = 0;

	if( bits > 0 ) {
		int factor = int(pow(2.0, bits-1));
		num = (byte % (factor*2));

		if ( (byte & factor) == factor ) {
			num -= factor*2;
		}
	}

	return num;
}

bool BarsParse::parseNoteRest(MeasureData* measureData, int length, BdatType type) {
	NoteContainer* container = new NoteContainer();
	Block placeHolder;
	unsigned int thisByte;

	measureData->addNoteContainer(container);
	measureData->addMusicData(container);

	// note|rest & grace
	container->setIsRest(type==Bdat_Rest);
	container->setIsRaw(type==Bdat_Raw_Note);

	if( !readBuffer(placeHolder, 2) ) { return false; }
	thisByte = placeHolder.toUnsignedInt();
	container->setIsGrace( thisByte == 0x3C00 );
	container->setIsCue( thisByte == 0x4B40 || thisByte == 0x3240 );

	// show / hide
	if( !readBuffer(placeHolder, 1) ) { return false; }
	thisByte = placeHolder.toUnsignedInt();
	container->setShow(getLowNibble(thisByte)!=0x8);

	// voice
	container->setVoice(getLowNibble(thisByte)&0x7);

	// common
	if( !parseCommonBlock(container) ) { return false; }

	// tuplet
	if( !readBuffer(placeHolder, 1) ) { return false; }
	container->setTuplet(placeHolder.toUnsignedInt());

	// space
	if( !readBuffer(placeHolder, 1) ) { return false; }
	container->setSpace(placeHolder.toUnsignedInt());

	// in beam
	if( !readBuffer(placeHolder, 1) ) { return false; }
	thisByte = placeHolder.toUnsignedInt();
	bool inBeam = ( getHighNibble(thisByte) & 0x1 ) == 0x1;
	container->setInBeam(inBeam);

	// grace NoteType
	container->setGraceNoteType((NoteType)getHighNibble(thisByte));

	// dot
	container->setDot(getLowNibble(thisByte)&0x03);

	// NoteType
	if( !readBuffer(placeHolder, 1) ) { return false; }
	thisByte = placeHolder.toUnsignedInt();
	container->setNoteType((NoteType)getLowNibble(thisByte));

	int cursor = 0;

	if( type == Bdat_Rest ) {
		Note* rest = new Note();
		container->addNoteRest(rest);
		rest->setIsRest(true);

		// line
		if( !readBuffer(placeHolder, 1) ) { return false; }
		rest->setLine(placeHolder.toInt());

		if( !jump(1) ) { return false; }

		cursor = ove_->getIsVersion4() ? 16 : 14;
	} else // type == Bdat_Note || type == Bdat_Raw_Note
	{
		// stem up 0x80, stem down 0x00
		if( !readBuffer(placeHolder, 1) ) { return false; }
		thisByte = placeHolder.toUnsignedInt();
		container->setStemUp((getHighNibble(thisByte)&0x8)==0x8);

		// stem length
		int stemOffset = thisByte%0x80;
		container->setStemLength(getInt(stemOffset, 7)+7/*3.5 line span*/);

		// show stem 0x00, hide stem 0x40
		if( !readBuffer(placeHolder, 1) ) { return false; }
		bool hideStem = getHighNibble(thisByte)==0x4;
		container->setShowStem(!hideStem);

		if( !jump(1) ) { return false; }

		// note count
		if( !readBuffer(placeHolder, 1) ) { return false; }
		unsigned int noteCount = placeHolder.toUnsignedInt();
		unsigned int i;

		// each note 16 bytes
		for( i=0; i<noteCount; ++i ) {
			Note* notePtr = new Note();
			notePtr->setIsRest(false);

			container->addNoteRest(notePtr);

			// note show / hide
			if( !readBuffer(placeHolder, 1) ) { return false; }
			thisByte = placeHolder.toUnsignedInt();
			notePtr->setShow((thisByte&0x80) != 0x80);

			// note head type
			notePtr->setHeadType(thisByte&0x7f);

			// tie pos
			if( !readBuffer(placeHolder, 1) ) { return false; }
			thisByte = placeHolder.toUnsignedInt();
			notePtr->setTiePos(getHighNibble(thisByte));

			// offset staff, in {-1, 0, 1}
			if( !readBuffer(placeHolder, 1) ) { return false; }
			thisByte = getLowNibble(placeHolder.toUnsignedInt());
			int offsetStaff = 0;
			if( thisByte == 1 ) { offsetStaff = 1; }
			if( thisByte == 7 ) { offsetStaff = -1; }
			notePtr->setOffsetStaff(offsetStaff);

			// accidental
			if( !readBuffer(placeHolder, 1) ) { return false; }
			thisByte = placeHolder.toUnsignedInt();
			notePtr->setAccidental(getLowNibble(thisByte));
			// accidental 0: influenced by key, 4: influenced by previous accidental in measure
			bool notShow = ( getHighNibble(thisByte) == 0 ) || ( getHighNibble(thisByte) == 4 );
			notePtr->setShowAccidental(!notShow);

			if( !jump(1) ) { return false; }

			// line
			if( !readBuffer(placeHolder, 1) ) { return false; }
			notePtr->setLine(placeHolder.toInt());

			if( !jump(1) ) { return false; }

			// note
			if( !readBuffer(placeHolder, 1) ) { return false; }
			unsigned int note = placeHolder.toUnsignedInt();
			notePtr->setNote(note);

			// note on velocity
			if( !readBuffer(placeHolder, 1) ) { return false; }
			unsigned int onVelocity = placeHolder.toUnsignedInt();
			notePtr->setOnVelocity(onVelocity);

			// note off velocity
			if( !readBuffer(placeHolder, 1) ) { return false; }
			unsigned int offVelocity = placeHolder.toUnsignedInt();
			notePtr->setOffVelocity(offVelocity);

			if( !jump(2) ) { return false; }

			// length (tick)
			if( !readBuffer(placeHolder, 2) ) { return false; }
			container->setLength(placeHolder.toUnsignedInt());

			// offset tick
			if( !readBuffer(placeHolder, 2) ) { return false; }
			notePtr->setOffsetTick(placeHolder.toInt());
		}

		cursor = ove_->getIsVersion4() ? 18 : 16;
		cursor += noteCount * 16/*note size*/;
	}

	// articulation
	while ( cursor < length + 1/* 0x70 || 0x80 || 0x90 */ ) {
		Articulation* art = new Articulation();
		container->addArticulation(art);

		// block size
		if( !readBuffer(placeHolder, 2) ) { return false; }
		int blockSize = placeHolder.toUnsignedInt();

		// articulation type
		if( !readBuffer(placeHolder, 1) ) { return false; }
		art->setArtType(placeHolder.toUnsignedInt());

		// placement
		if( !readBuffer(placeHolder, 1) ) { return false; }
		art->setPlacementAbove(placeHolder.toUnsignedInt()!=0x00);	//0x00:below, 0x30:above

		// offset
		if( !parseOffsetElement(art) ) { return false; }

		if( !ove_->getIsVersion4() ) {
			if( blockSize - 8 > 0 ) {
				if( !jump(blockSize-8) ) { return false; }
			}
		} else {
			// setting
			if( !readBuffer(placeHolder, 1) ) { return false; }
			thisByte = placeHolder.toUnsignedInt();
			const bool changeSoundEffect = ( ( thisByte & 0x1 ) == 0x1 );
			const bool changeLength = ( ( thisByte & 0x2 ) == 0x2 );
			const bool changeVelocity = ( ( thisByte & 0x4 ) == 0x4 );
			//const bool changeExtraLength = ( ( thisByte & 0x20 ) == 0x20 );

			if( !jump(8) ) { return false; }

			// velocity type
			if( !readBuffer(placeHolder, 1) ) { return false; }
			thisByte = placeHolder.toUnsignedInt();
			if( changeVelocity ) {
				art->setVelocityType((Articulation::VelocityType)thisByte);
			}

			if( !jump(14) ) { return false; }

			// sound effect
			if( !readBuffer(placeHolder, 2) ) { return false; }
			int from = placeHolder.toInt();
			if( !readBuffer(placeHolder, 2) ) { return false; }
			int to = placeHolder.toInt();
			if( changeSoundEffect ) {
				art->setSoundEffect(from, to);
			}

			if( !jump(1) ) { return false; }

			// length percentage
			if( !readBuffer(placeHolder, 1) ) { return false; }
			if( changeLength ) {
				art->setLengthPercentage(placeHolder.toUnsignedInt());
			}

			// velocity
			if( !readBuffer(placeHolder, 2) ) { return false; }
			if( changeVelocity ) {
				art->setVelocityValue(placeHolder.toInt());
			}

			if( Articulation::isTrill(art->getArtType()) ) {
				if( !jump(8) ) { return false; }

				// trill note length
				if( !readBuffer(placeHolder, 1) ) { return false; }
				art->setTrillNoteLength(placeHolder.toUnsignedInt());

				// trill rate
				if( !readBuffer(placeHolder, 1) ) { return false; }
				thisByte = placeHolder.toUnsignedInt();
				NoteType trillNoteType = Note_Sixteen;
				switch ( getHighNibble(thisByte) ) {
				case 0:
					trillNoteType = Note_None;
					break;
				case 1:
					trillNoteType = Note_Sixteen;
					break;
				case 2:
					trillNoteType = Note_32;
					break;
				case 3:
					trillNoteType = Note_64;
					break;
				case 4:
					trillNoteType = Note_128;
					break;
				default:
					break;
				}
				art->setTrillRate(trillNoteType);

				// accelerate type
				art->setAccelerateType(thisByte&0xf);

				if( !jump(1) ) { return false; }

				// auxiliary first
				if( !readBuffer(placeHolder, 1) ) { return false; }
				art->setAuxiliaryFirst(placeHolder.toBoolean());

				if( !jump(1) ) { return false; }

				// trill interval
				if( !readBuffer(placeHolder, 1) ) { return false; }
				art->setTrillInterval(placeHolder.toUnsignedInt());
			} else {
				if( blockSize > 40 ) {
					if( !jump( blockSize - 40 ) ) { return false; }
				}
			}
		}

		cursor += blockSize;
	}

	return true;
}

int tupletToSpace(int tuplet) {
	int a(1);

	while( a*2 < tuplet ) {
		a *= 2;
	}

	return a;
}

bool BarsParse::parseBeam(MeasureData* measureData, int length) {
	int i;
	Block placeHolder;

	Beam* beam = new Beam();
	measureData->addCrossMeasureElement(beam, true);

	// maybe create tuplet, for < quarter & tool 3(
	bool createTuplet = false;
	int maxEndUnit = 0;
	Tuplet* tuplet = new Tuplet();

	// is grace
	if( !readBuffer(placeHolder, 1) ) { return false; }
	beam->setIsGrace(placeHolder.toBoolean());

	if( !jump(1) ) { return false; }

	// voice
	if( !readBuffer(placeHolder, 1) ) { return false; }
	beam->setVoice(getLowNibble(placeHolder.toUnsignedInt())&0x7);

	// common
	if( !parseCommonBlock(beam) ) { return false; }

	if( !jump(2) ) { return false; }

	// beam count
	if( !readBuffer(placeHolder, 1) ) { return false; }
	int beamCount = placeHolder.toUnsignedInt();

	if( !jump(1) ) { return false; }

	// left line
	if( !readBuffer(placeHolder, 1) ) { return false; }
	beam->getLeftLine()->setLine(placeHolder.toInt());

	// right line
	if( !readBuffer(placeHolder, 1) ) { return false; }
	beam->getRightLine()->setLine(placeHolder.toInt());

	if( ove_->getIsVersion4() ) {
		if( !jump(8) ) { return false; }
	}

	int currentCursor = ove_->getIsVersion4() ? 23 : 13;
	int count = (length - currentCursor)/16;

	if( count != beamCount ) { return false; }

	for( i=0; i<count; ++i ) {
		if( !jump(1) ) { return false; }

		// tuplet
		if( !readBuffer(placeHolder, 1) ) { return false; }
		int tupletCount = placeHolder.toUnsignedInt();
		if( tupletCount > 0 ) {
			createTuplet = true;
			tuplet->setTuplet(tupletCount);
			tuplet->setSpace(tupletToSpace(tupletCount));
		}

		// start / stop measure
		// line i start end position
		MeasurePos startMp;
		MeasurePos stopMp;

		if( !readBuffer(placeHolder, 1) ) { return false; }
		startMp.setMeasure(placeHolder.toUnsignedInt());
		if( !readBuffer(placeHolder, 1) ) { return false; }
		stopMp.setMeasure(placeHolder.toUnsignedInt());

		if( !readBuffer(placeHolder, 2) ) { return false; }
		startMp.setOffset(placeHolder.toInt());
		if( !readBuffer(placeHolder, 2) ) { return false; }
		stopMp.setOffset(placeHolder.toInt());

		beam->addLine(startMp, stopMp);

		if( stopMp.getOffset() > maxEndUnit ) {
			maxEndUnit = stopMp.getOffset();
		}

		if( i == 0 ) {
			if( !jump(4) ) { return false; }

			// left offset up+4, down-4
			if( !readBuffer(placeHolder, 2) ) { return false; }
			beam->getLeftShoulder()->setYOffset(placeHolder.toInt());

			// right offset up+4, down-4
			if( !readBuffer(placeHolder, 2) ) { return false; }
			beam->getRightShoulder()->setYOffset(placeHolder.toInt());
		} else {
			if( !jump(8) ) { return false; }
		}
	}

	const QList<QPair<MeasurePos, MeasurePos> > lines = beam->getLines();
	MeasurePos offsetMp;

	for( i=0; i<lines.size(); ++i ) {
		if( lines[i].second > offsetMp ) {
			offsetMp = lines[i].second;
		}
	}

	beam->stop()->setMeasure(offsetMp.getMeasure());
	beam->stop()->setOffset(offsetMp.getOffset());

	// a case that Tuplet block don't exist, and hide inside beam
	if( createTuplet ) {
		tuplet->copyCommonBlock(*beam);
		tuplet->getLeftLine()->setLine(beam->getLeftLine()->getLine());
		tuplet->getRightLine()->setLine(beam->getRightLine()->getLine());
		tuplet->stop()->setMeasure(beam->stop()->getMeasure());
		tuplet->stop()->setOffset(maxEndUnit);

		measureData->addCrossMeasureElement(tuplet, true);
	} else {
		delete tuplet;
	}

	return true;
}

bool BarsParse::parseTie(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	Tie* tie = new Tie();
	measureData->addCrossMeasureElement(tie, true);

	if( !jump(3) ) { return false; }

	// start common
	if( !parseCommonBlock(tie) ) { return false; }

	if( !jump(1) ) { return false; }

	// note
	if( !readBuffer(placeHolder, 1) ) { return false; }
	tie->setNote(placeHolder.toUnsignedInt());

	// pair lines
	if( !parsePairLinesBlock(tie) ) { return false; }

	// offset common
	if( !parseOffsetCommonBlock(tie) ) { return false; }

	// left shoulder offset
	if( !parseOffsetElement(tie->getLeftShoulder()) ) { return false; }

	// right shoulder offset
	if( !parseOffsetElement(tie->getRightShoulder()) ) { return false; }

	// height
	if( !readBuffer(placeHolder, 2) ) { return false; }
	tie->setHeight(placeHolder.toUnsignedInt());

	return true;
}

bool BarsParse::parseTuplet(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	Tuplet* tuplet = new Tuplet();
	measureData->addCrossMeasureElement(tuplet, true);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(tuplet) ) { return false; }

	if( !jump(2) ) { return false; }

	// pair lines
	if( !parsePairLinesBlock(tuplet) ) { return false; }

	// offset common
	if( !parseOffsetCommonBlock(tuplet) ) { return false; }

	// left shoulder offset
	if( !parseOffsetElement(tuplet->getLeftShoulder()) ) { return false; }

	// right shoulder offset
	if( !parseOffsetElement(tuplet->getRightShoulder()) ) { return false; }

	if( !jump(2) ) { return false; }

	// height
	if( !readBuffer(placeHolder, 2) ) { return false; }
	tuplet->setHeight(placeHolder.toUnsignedInt());

	// tuplet
	if( !readBuffer(placeHolder, 1) ) { return false; }
	tuplet->setTuplet(placeHolder.toUnsignedInt());

	// space
	if( !readBuffer(placeHolder, 1) ) { return false; }
	tuplet->setSpace(placeHolder.toUnsignedInt());

	// mark offset
	if( !parseOffsetElement(tuplet->getMarkHandle()) ) { return false; }

	return true;
}

HarmonyType binaryToHarmonyType(int bin) {
	HarmonyType type = Harmony_maj;
	if( bin == 0x0091 ) {
		type = Harmony_maj;
	} else if( bin == 0x0089 ) {
		type = Harmony_min;
	} else if( bin == 0x0489 ) {
		type = Harmony_min7;
	} else if( bin == 0x0491 ) {
		type = Harmony_7;
	} else if( bin == 0x0495 ) {
		type = Harmony_9;
	} else if( bin == 0x0449 ) {
		type = Harmony_min7b5;
	} else if( bin == 0x04A1 ) {
		type = Harmony_7sus4;
	} else if( bin == 0x00A1 ) {
		type = Harmony_sus4;
	} else if( bin == 0x0049 ) {
		type = Harmony_dim;
	} else if( bin == 0x0249 ) {
		type = Harmony_dim7;
	} else if( bin == 0x0111 ) {
		type = Harmony_aug;
	} else if( bin == 0x0511 ) {
		type = Harmony_aug7;
	} else if( bin == 0x044D ) {
		type = Harmony_min9_b5;
	} else if( bin == 0x0499 ) {
		type = Harmony_7s9;
	} else if( bin == 0x0615 ) {
		type = Harmony_13;
	} else if( bin == 0x0289 ) {
		type = Harmony_min6;
	} else if( bin == 0x0291 ) {
		type = Harmony_6;
	} else if( bin == 0x0295 ) {
		type = Harmony_6; 	//6add9
	} else if( bin == 0x0095 ) {
		type = Harmony_min; //minor add9
	} else if( bin == 0x008D ) {
		type = Harmony_maj7;
	} else if( bin == 0x0891 ) {
		type = Harmony_maj7;
	} else if( bin == 0x0881 ) {
		type = Harmony_maj7_s5;	//maj7#5
	} else if( bin == 0x0911 ) {
		type = Harmony_maj7_s5;	//maj7#5
	} else if( bin == 0x0991 ) {
		type = Harmony_maj7_s11;//maj7#11
	} else if( bin == 0x0851 ) {
		type = Harmony_maj7_s11;//maj7#11
	} else if( bin == 0x08D1 ) {
		type = Harmony_maj9;
	} else if( bin == 0x0895 ) {
		type = Harmony_maj9_s5;	//maj9#5
	} else if( bin == 0x0995 ) {
		type = Harmony_maj13_s11;//maj9#11
	} else if( bin == 0x0855 ) {
		type = Harmony_maj9_s11;//maj9#11
	} else if( bin == 0x08D5 ) {
		type = Harmony_maj13;
	} else if( bin == 0x0A95 ) {
		type = Harmony_maj13_s11;//maj13#11
	} else if( bin == 0x0A55 ) {
		type = Harmony_maj13;	//maj13(no3)
	} else if( bin == 0x0A85 ) {
		type = Harmony_maj9_s5;	//maj13#5#11(no4)
	} else if( bin == 0x0B45 ) {
		type = Harmony_7b9;
	} else if( bin == 0x0493 ) {
		type = Harmony_7b5;
	} else if( bin == 0x0451 ) {
		type = Harmony_9b5;
	} else if( bin == 0x0455 ) {
		type = Harmony_7s9;		//7#5#9
	} else if( bin == 0x0519 ) {
		type = Harmony_7b9;		//7#5b9
	} else if( bin == 0x0513 ) {
		type = Harmony_aug7;	//aug9
	} else if( bin == 0x0515 ) {
		type = Harmony_sus4;	//sus9
	} else if( bin == 0x04A5 ) {
		type = Harmony_13b9;
	} else if( bin == 0x0613 ) {
		type = Harmony_13b9;	//13b9#11
	} else if( bin == 0x0611 ) {
		type = Harmony_13;
	} else if( bin == 0x0653 ) {
		type = Harmony_min;		//m(natural7)
	} else if( bin == 0x0889 ) {
		type = Harmony_min9;	//m9(natural7)
	} else if( bin == 0x088D ) {
		type = Harmony_min11;
	} else if( bin == 0x04AD ) {
		type = Harmony_9s11;
	} else if( bin == 0x04D5 ) {
		type = Harmony_7sus4;	//sus7
	} else if( bin == 0x0421 ) {
		type = Harmony_min11;
	} else if( bin == 0x04A9 ) {
		type = Harmony_min9;
	} else if( bin == 0x048D ) {
		type = Harmony_7b5b9;
	} else if( bin == 0x0453 ) {
		type = Harmony_maj;		//(no5)
	} else if( bin == 0x0011 ) {
		type = Harmony_maj7;	//(no3)
	} else if( bin == 0x0081 ) {
		type = Harmony_7;		//7(no3)
	} else if( bin == 0x0481 ) {
		type = Harmony_7;		//7(no5)
	} else if( bin == 0x0411 ) {
		type = Harmony_6;
	} else if( bin == 0x0291 ) {
		type = Harmony_sus4;	//sus(add9)
	} else if( bin == 0x00A5 ) {
		type = Harmony_13s9;	//13#9b5
	} else if( bin == 0x0659 ) {
		type = Harmony_sus4;	//sus(no5)
	} else if( bin == 0x0021 ) {
		type = Harmony_7b5b9;	//7b5b9#9
	} else if( bin == 0x045B ) {
		type = Harmony_13b5;	//13b5b9#9
	} else if( bin == 0x065B ) {
		type = Harmony_13b9;	//13b9#9
	} else if( bin == 0x061B ) {
		type = Harmony_7b9s9;	//7b9#9
	} else if( bin == 0x04B5 ) {
		type = Harmony_7;
	}

	return type;
}

bool BarsParse::parseHarmony(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	Harmony* harmony = new Harmony();
	measureData->addMusicData(harmony);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(harmony) ) { return false; }

	// bass on bottom
	if( !readBuffer(placeHolder, 1) ) { return false; }
	harmony->setBassOnBottom((getHighNibble(placeHolder.toUnsignedInt())==0x4));

	if( !jump(1) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	harmony->setYOffset(placeHolder.toInt());

	// harmony type
	if( !readBuffer(placeHolder, 2) ) { return false; }
	harmony->setHarmonyType(binaryToHarmonyType(placeHolder.toUnsignedInt()));

	// root
	if( !readBuffer(placeHolder, 1) ) { return false; }
	harmony->setRoot(placeHolder.toInt());

	// bass
	if( !readBuffer(placeHolder, 1) ) { return false; }
	harmony->setBass(placeHolder.toInt());

	// angle
	if( !readBuffer(placeHolder, 2) ) { return false; }
	harmony->setAngle(placeHolder.toInt());

	if( ove_->getIsVersion4() ) {
		// length (tick)
		if( !readBuffer(placeHolder, 2) ) { return false; }
		harmony->setLength(placeHolder.toUnsignedInt());

		if( !jump(4) ) { return false; }
	}

	return true;
}

bool BarsParse::parseClef(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	Clef* clef = new Clef();
	measureData->addMusicData(clef);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(clef) ) { return false; }

	// clef type
	if( !readBuffer(placeHolder, 1) ) { return false; }
	clef->setClefType(placeHolder.toUnsignedInt());

	// line
	if( !readBuffer(placeHolder, 1) ) { return false; }
	clef->setLine(placeHolder.toInt());

	if( !jump(2) ) { return false; }

	return true;
}

bool BarsParse::parseLyric(MeasureData* measureData, int length) {
	Block placeHolder;

	Lyric* lyric = new Lyric();
	measureData->addMusicData(lyric);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(lyric) ) { return false; }

	if( !jump(2) ) { return false; }

	// offset
	if( !parseOffsetElement(lyric) ) { return false; }

	if( !jump(7) ) { return false; }

	// verse
	if( !readBuffer(placeHolder, 1) ) { return false; }
	lyric->setVerse(placeHolder.toUnsignedInt());

	if( ove_->getIsVersion4() ) {
		if( !jump(6) ) { return false; }

		// lyric
		if( length > 29 ) {
			if( !readBuffer(placeHolder, length-29) ) { return false; }
			lyric->setLyric(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));
		}
	}

	return true;
}

bool BarsParse::parseSlur(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	Slur* slur = new Slur();
	measureData->addCrossMeasureElement(slur, true);

	if( !jump(2) ) { return false; }

	// voice
	if( !readBuffer(placeHolder, 1) ) { return false; }
	slur->setVoice(getLowNibble(placeHolder.toUnsignedInt())&0x7);

	// common
	if( !parseCommonBlock(slur) ) { return false; }

	// show on top
	if( !readBuffer(placeHolder, 1) ) { return false; }
	slur->setShowOnTop(getHighNibble(placeHolder.toUnsignedInt())==0x8);

	if( !jump(1) ) { return false; }

	// pair lines
	if( !parsePairLinesBlock(slur) ) { return false; }

	// offset common
	if( !parseOffsetCommonBlock(slur) ) { return false; }

	// handle 1
	if( !parseOffsetElement(slur->getLeftShoulder()) ) { return false; }

	// handle 4
	if( !parseOffsetElement(slur->getRightShoulder()) ) { return false; }

	// handle 2
	if( !parseOffsetElement(slur->getHandle2()) ) { return false; }

	// handle 3
	if( !parseOffsetElement(slur->getHandle3()) ) { return false; }

	if( ove_->getIsVersion4() ) {
		if( !jump(3) ) { return false; }

		// note time percent
		if( !readBuffer(placeHolder, 1) ) { return false; }
		slur->setNoteTimePercent(placeHolder.toUnsignedInt());

		if( !jump(36) ) { return false; }
	}

	return true;
}

bool BarsParse::parseGlissando(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	Glissando* glissando = new Glissando();
	measureData->addCrossMeasureElement(glissando, true);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(glissando) ) { return false; }

	// straight or wavy
	if( !readBuffer(placeHolder, 1) ) { return false; }
	unsigned int thisByte = placeHolder.toUnsignedInt();
	glissando->setStraightWavy(getHighNibble(thisByte)==4);

	if( !jump(1) ) { return false; }

	// pair lines
	if( !parsePairLinesBlock(glissando) ) { return false; }

	// offset common
	if( !parseOffsetCommonBlock(glissando) ) { return false; }

	// left shoulder
	if( !parseOffsetElement(glissando->getLeftShoulder()) ) { return false; }

	// right shoulder
	if( !parseOffsetElement(glissando->getRightShoulder()) ) { return false; }

	if( ove_->getIsVersion4() ) {
		if( !jump(1) ) { return false; }

		// line thick
		if( !readBuffer(placeHolder, 1) ) { return false; }
		glissando->setLineThick(placeHolder.toUnsignedInt());

		if( !jump(12) ) { return false; }

		// text 32 bytes
		if( !readBuffer(placeHolder, 32) ) { return false; }
		glissando->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));

		if( !jump(6) ) { return false; }
	}

	return true;
}

bool getDecoratorType(
			unsigned int thisByte,
			bool& measureRepeat,
			Decorator::DecoratorType& decoratorType,
			bool& singleRepeat,
			ArticulationType& artType) {
	measureRepeat = false;
	decoratorType = Decorator::Decorator_Articulation;
	singleRepeat = true;
	artType = Articulation_None;

	switch (thisByte) {
	case 0x00: {
		decoratorType = Decorator::Decorator_Dotted_Barline;
		break;
	}
	case 0x30: {
		artType = Articulation_Open_String;
		break;
	}
	case 0x31: {
		artType = Articulation_Finger_1;
		break;
	}
	case 0x32: {
		artType = Articulation_Finger_2;
		break;
	}
	case 0x33: {
		artType = Articulation_Finger_3;
		break;
	}
	case 0x34: {
		artType = Articulation_Finger_4;
		break;
	}
	case 0x35: {
		artType = Articulation_Finger_5;
		break;
	}
	case 0x6B: {
		artType = Articulation_Flat_Accidental_For_Trill;
		break;
	}
	case 0x6C: {
		artType = Articulation_Sharp_Accidental_For_Trill;
		break;
	}
	case 0x6D: {
		artType = Articulation_Natural_Accidental_For_Trill;
		break;
	}
	case 0x8d: {
		measureRepeat = true;
		singleRepeat = true;
		break;
	}
	case 0x8e: {
		measureRepeat = true;
		singleRepeat = false;
		break;
	}
	case 0xA0: {
		artType = Articulation_Minor_Trill;
		break;
	}
	case 0xA1: {
		artType = Articulation_Major_Trill;
		break;
	}
	case 0xA2: {
		artType = Articulation_Trill_Section;
		break;
	}
	case 0xA6: {
		artType = Articulation_Turn;
		break;
	}
	case 0xA8: {
		artType = Articulation_Tremolo_Eighth;
		break;
	}
	case 0xA9: {
		artType = Articulation_Tremolo_Sixteenth;
		break;
	}
	case 0xAA: {
		artType = Articulation_Tremolo_Thirty_Second;
		break;
	}
	case 0xAB: {
		artType = Articulation_Tremolo_Sixty_Fourth;
		break;
	}
	case 0xB2: {
		artType = Articulation_Fermata;
		break;
	}
	case 0xB3: {
		artType = Articulation_Fermata_Inverted;
		break;
	}
	case 0xB9: {
		artType = Articulation_Pause;
		break;
	}
	case 0xBA: {
		artType = Articulation_Grand_Pause;
		break;
	}
	case 0xC0: {
		artType = Articulation_Marcato;
		break;
	}
	case 0xC1: {
		artType = Articulation_Marcato_Dot;
		break;
	}
	case 0xC2: {
		artType = Articulation_SForzando;
		break;
	}
	case 0xC3: {
		artType = Articulation_SForzando_Dot;
		break;
	}
	case 0xC4: {
		artType = Articulation_SForzando_Inverted;
		break;
	}
	case 0xC5: {
		artType = Articulation_SForzando_Dot_Inverted;
		break;
	}
	case 0xC6: {
		artType = Articulation_Staccatissimo;
		break;
	}
	case 0xC7: {
		artType = Articulation_Staccato;
		break;
	}
	case 0xC8: {
		artType = Articulation_Tenuto;
		break;
	}
	case 0xC9: {
		artType = Articulation_Natural_Harmonic;
		break;
	}
	case 0xCA: {
		artType = Articulation_Artificial_Harmonic;
		break;
	}
	case 0xCB: {
		artType = Articulation_Plus_Sign;
		break;
	}
	case 0xCC: {
		artType = Articulation_Up_Bow;
		break;
	}
	case 0xCD: {
		artType = Articulation_Down_Bow;
		break;
	}
	case 0xCE: {
		artType = Articulation_Up_Bow_Inverted;
		break;
	}
	case 0xCF: {
		artType = Articulation_Down_Bow_Inverted;
		break;
	}
	case 0xD0: {
		artType = Articulation_Pedal_Down;
		break;
	}
	case 0xD1: {
		artType = Articulation_Pedal_Up;
		break;
	}
	case 0xD6: {
		artType = Articulation_Heavy_Attack;
		break;
	}
	case 0xD7: {
		artType = Articulation_Heavier_Attack;
		break;
	}
	default:
		return false;
		break;
	}

	return true;
}

bool BarsParse::parseDecorators(MeasureData* measureData, int length) {
	Block placeHolder;
	MusicData* musicData = new MusicData();

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(musicData) ) { return false; }

	if( !jump(2) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	musicData->setYOffset(placeHolder.toInt());

	if( !jump(2) ) { return false; }

	// measure repeat | piano pedal | dotted barline | articulation
	if( !readBuffer(placeHolder, 1) ) { return false; }
	unsigned int thisByte = placeHolder.toUnsignedInt();

	Decorator::DecoratorType decoratorType;
	bool isMeasureRepeat;
	bool isSingleRepeat = true;
	ArticulationType artType = Articulation_None;

	getDecoratorType(thisByte, isMeasureRepeat, decoratorType, isSingleRepeat, artType);

	if( isMeasureRepeat ) {
		MeasureRepeat* measureRepeat = new MeasureRepeat();
		measureData->addCrossMeasureElement(measureRepeat, true);

		measureRepeat->copyCommonBlock(*musicData);
		measureRepeat->setYOffset(musicData->getYOffset());

		measureRepeat->setSingleRepeat(isSingleRepeat);
	} else {
		Decorator* decorator = new Decorator();
		measureData->addMusicData(decorator);

		decorator->copyCommonBlock(*musicData);
		decorator->setYOffset(musicData->getYOffset());

		decorator->setDecoratorType(decoratorType);
		decorator->setArticulationType(artType);
	}

	int cursor = ove_->getIsVersion4() ? 16 : 14;
	if( !jump(length-cursor) ) { return false; }

	return true;
}

bool BarsParse::parseWedge(MeasureData* measureData, int length) {
	Block placeHolder;
	Wedge* wedge = new Wedge();

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(wedge) ) { return false; }

	// wedge type
	if( !readBuffer(placeHolder, 1) ) { return false; }
	WedgeType wedgeType = Wedge_Cres_Line;
	bool wedgeOrExpression = true;
	unsigned int highHalfByte = getHighNibble(placeHolder.toUnsignedInt());
	unsigned int lowHalfByte = getLowNibble(placeHolder.toUnsignedInt());

	switch (highHalfByte) {
	case 0x0: {
		wedgeType = Wedge_Cres_Line;
		wedgeOrExpression = true;
		break;
	}
	case 0x4: {
		wedgeType = Wedge_Decresc_Line;
		wedgeOrExpression = true;
		break;
	}
	case 0x6: {
		wedgeType = Wedge_Decresc;
		wedgeOrExpression = false;
		break;
	}
	case 0x2: {
		wedgeType = Wedge_Cres;
		wedgeOrExpression = false;
		break;
	}
	default:
		break;
	}

	// 0xb | 0x8(ove3) , else 3, 0(ove3)
	if( (lowHalfByte & 0x8) == 0x8 ) {
		wedgeType = Wedge_Double_Line;
		wedgeOrExpression = true;
	}

	if( !jump(1) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	wedge->setYOffset(placeHolder.toInt());

	// wedge
	if( wedgeOrExpression ) {
		measureData->addCrossMeasureElement(wedge, true);
		wedge->setWedgeType(wedgeType);

		if( !jump(2) ) { return false; }

		// height
		if( !readBuffer(placeHolder, 2) ) { return false; }
		wedge->setHeight(placeHolder.toUnsignedInt());

		// offset common
		if( !parseOffsetCommonBlock(wedge) ) { return false; }

		int cursor = ove_->getIsVersion4() ? 21 : 19;
		if( !jump(length-cursor) ) { return false; }
	}
	// expression : cresc, decresc
	else {
		Expressions* express = new Expressions();
		measureData->addMusicData(express);

		express->copyCommonBlock(*wedge);
		express->setYOffset(wedge->getYOffset());

		if( !jump(4) ) { return false; }

		// offset common
		if( !parseOffsetCommonBlock(express) ) { return false; }

		if( ove_->getIsVersion4() ) {
			if( !jump(18) ) { return false; }

			// words
			if( length > 39 ) {
				if( !readBuffer(placeHolder, length-39) ) { return false; }
				express->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));
			}
		} else {
			QString str = wedgeType==Wedge_Cres ? "cresc" : "decresc";
			express->setText(str);

			if( !jump(8) ) { return false; }
		}
	}

	return true;
}

bool BarsParse::parseDynamics(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	Dynamics* dynamics = new Dynamics();
	measureData->addMusicData(dynamics);

	if( !jump(1) ) { return false; }

	// is playback
	if( !readBuffer(placeHolder, 1) ) { return false; }
	dynamics->setIsPlayback(getHighNibble(placeHolder.toUnsignedInt())!=0x4);

	if( !jump(1) ) { return false; }

	// common
	if( !parseCommonBlock(dynamics) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	dynamics->setYOffset(placeHolder.toInt());

	// dynamics type
	if( !readBuffer(placeHolder, 1) ) { return false; }
	dynamics->setDynamicsType(getLowNibble(placeHolder.toUnsignedInt()));

	// velocity
	if( !readBuffer(placeHolder, 1) ) { return false; }
	dynamics->setVelocity(placeHolder.toUnsignedInt());

	int cursor = ove_->getIsVersion4() ? 4 : 2;

	if( !jump(cursor) ) { return false; }

	return true;
}

bool BarsParse::parseKey(MeasureData* measureData, int /*length*/) {
	Block placeHolder;
	Key* key = measureData->getKey();
	int cursor = ove_->getIsVersion4() ? 9 : 7;

	if( !jump(cursor) ) { return false; }

	// key
	if( !readBuffer(placeHolder, 1) ) { return false; }
	key->setKey(oveKeyToKey(placeHolder.toUnsignedInt()));

	// previous key
	if( !readBuffer(placeHolder, 1) ) { return false; }
	key->setPreviousKey(oveKeyToKey(placeHolder.toUnsignedInt()));

	if( !jump(3) ) { return false; }

	// symbol count
	if( !readBuffer(placeHolder, 1) ) { return false; }
	key->setSymbolCount(placeHolder.toUnsignedInt());

	if( !jump(4) ) { return false; }

	return true;
}

bool BarsParse::parsePedal(MeasureData* measureData, int length) {
	Block placeHolder;

	Pedal* pedal = new Pedal();
	//measureData->addMusicData(pedal); //can't remember why
	measureData->addCrossMeasureElement(pedal, true);

	if( !jump(1) ) { return false; }

	// is playback
	if( !readBuffer(placeHolder, 1) ) { return false; }
	pedal->setIsPlayback(getHighNibble(placeHolder.toUnsignedInt())!=4);

	if( !jump(1) ) { return false; }

	// common
	if( !parseCommonBlock(pedal) ) { return false; }

	if( !jump(2) ) { return false; }

	// pair lines
	if( !parsePairLinesBlock(pedal) ) { return false; }

	// offset common
	if( !parseOffsetCommonBlock(pedal) ) { return false; }

	// left shoulder
	if( !parseOffsetElement(pedal->getLeftShoulder()) ) { return false; }

	// right shoulder
	if( !parseOffsetElement(pedal->getRightShoulder()) ) { return false; }

	int cursor = ove_->getIsVersion4() ? 0x45 : 0x23;
	int blankCount = ove_->getIsVersion4() ? 42 : 10;

	pedal->setHalf( length > cursor );

	if( !jump(blankCount) ) { return false; }

	if( length > cursor ) {
		if( !jump(2) ) { return false; }

		// handle x offset
		if( !readBuffer(placeHolder, 2) ) { return false; }
		pedal->getPedalHandle()->setXOffset(placeHolder.toInt());

		if( !jump(6) ) { return false; }
	}

	return true;
}

bool BarsParse::parseKuohao(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	KuoHao* kuoHao = new KuoHao();
	measureData->addMusicData(kuoHao);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(kuoHao) ) { return false; }

	if( !jump(2) ) { return false; }

	// pair lines
	if( !parsePairLinesBlock(kuoHao) ) { return false; }

	if( !jump(4) ) { return false; }

	// left shoulder
	if( !parseOffsetElement(kuoHao->getLeftShoulder()) ) { return false; }

	// right shoulder
	if( !parseOffsetElement(kuoHao->getRightShoulder()) ) { return false; }

	// kuohao type
	if( !readBuffer(placeHolder, 1) ) { return false; }
	kuoHao->setKuohaoType(placeHolder.toUnsignedInt());

	// height
	if( !readBuffer(placeHolder, 1) ) { return false; }
	kuoHao->setHeight(placeHolder.toUnsignedInt());

	int jumpAmount = ove_->getIsVersion4() ? 40 : 8;
	if( !jump(jumpAmount) ) { return false; }

	return true;
}

bool BarsParse::parseExpressions(MeasureData* measureData, int length) {
	Block placeHolder;

	Expressions* expressions = new Expressions();
	measureData->addMusicData(expressions);

	if( !jump(3) ) { return false; }

	// common00
	if( !parseCommonBlock(expressions) ) { return false; }

	if( !jump(2) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	expressions->setYOffset(placeHolder.toInt());

	// range bar offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	//int barOffset = placeHolder.toUnsignedInt();

	if( !jump(10) ) { return false; }

	// tempo 1
	if( !readBuffer(placeHolder, 2) ) { return false; }
	//double tempo1 = ((double)placeHolder.toUnsignedInt()) / 100.0;

	// tempo 2
	if( !readBuffer(placeHolder, 2) ) { return false; }
	//double tempo2 = ((double)placeHolder.toUnsignedInt()) / 100.0;

	if( !jump(6) ) { return false; }

	// text
	int cursor = ove_->getIsVersion4() ? 35 : 33;
	if( length > cursor ) {
		if( !readBuffer(placeHolder, length-cursor) ) { return false; }
		expressions->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()));
	}

	return true;
}

bool BarsParse::parseHarpPedal(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	HarpPedal* harpPedal = new HarpPedal();
	measureData->addMusicData(harpPedal);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(harpPedal) ) { return false; }

	if( !jump(2) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	harpPedal->setYOffset(placeHolder.toInt());

	// show type
	if( !readBuffer(placeHolder, 1) ) { return false; }
	harpPedal->setShowType(placeHolder.toUnsignedInt());

	// show char flag
	if( !readBuffer(placeHolder, 1) ) { return false; }
	harpPedal->setShowCharFlag(placeHolder.toUnsignedInt());

	if( !jump(8) ) { return false; }

	return true;
}

bool BarsParse::parseMultiMeasureRest(MeasureData* measureData, int /*length*/) {
	Block placeHolder(2);
	MultiMeasureRest* measureRest = new MultiMeasureRest();
	measureData->addMusicData(measureRest);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(measureRest) ) { return false; }

	if( !jump(6) ) { return false; }

	return true;
}

bool BarsParse::parseHarmonyGuitarFrame(MeasureData* measureData, int length) {
	Block placeHolder;

	Harmony* harmony = new Harmony();
	measureData->addMusicData(harmony);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(harmony) ) { return false; }

	// root
	if( !readBuffer(placeHolder, 1) ) { return false; }
	harmony->setRoot(placeHolder.toUnsignedInt());

	// type
	if( !readBuffer(placeHolder, 1) ) { return false; }
	harmony->setHarmonyType((HarmonyType)placeHolder.toUnsignedInt());

	// bass
	if( !readBuffer(placeHolder, 1) ) { return false; }
	harmony->setBass(placeHolder.toUnsignedInt());

	int jumpAmount = ove_->getIsVersion4() ? length - 12 : length - 10;
	if( !jump(jumpAmount) ) { return false; }

	return true;
}

void extractOctave(unsigned int Bits, OctaveShiftType& octaveShiftType,	QList<OctaveShiftPosition>& positions) {
	octaveShiftType = OctaveShift_8;
	positions.clear();

	switch (Bits) {
	case 0x0: {
		octaveShiftType = OctaveShift_8;
		positions.push_back(OctavePosition_Continue);
		break;
	}
	case 0x1: {
		octaveShiftType = OctaveShift_Minus_8;
		positions.push_back(OctavePosition_Continue);
		break;
	}
	case 0x2: {
		octaveShiftType = OctaveShift_15;
		positions.push_back(OctavePosition_Continue);
		break;
	}
	case 0x3: {
		octaveShiftType = OctaveShift_Minus_15;
		positions.push_back(OctavePosition_Continue);
		break;
	}
	case 0x4: {
		octaveShiftType = OctaveShift_8;
		positions.push_back(OctavePosition_Stop);
		break;
	}
	case 0x5: {
		octaveShiftType = OctaveShift_Minus_8;
		positions.push_back(OctavePosition_Stop);
		break;
	}
	case 0x6: {
		octaveShiftType = OctaveShift_15;
		positions.push_back(OctavePosition_Stop);
		break;
	}
	case 0x7: {
		octaveShiftType = OctaveShift_Minus_15;
		positions.push_back(OctavePosition_Stop);
		break;
	}
	case 0x8: {
		octaveShiftType = OctaveShift_8;
		positions.push_back(OctavePosition_Start);
		break;
	}
	case 0x9: {
		octaveShiftType = OctaveShift_Minus_8;
		positions.push_back(OctavePosition_Start);
		break;
	}
	case 0xA: {
		octaveShiftType = OctaveShift_15;
		positions.push_back(OctavePosition_Start);
		break;
	}
	case 0xB: {
		octaveShiftType = OctaveShift_Minus_15;
		positions.push_back(OctavePosition_Start);
		;
		break;
	}
	case 0xC: {
		octaveShiftType = OctaveShift_8;
		positions.push_back(OctavePosition_Start);
		positions.push_back(OctavePosition_Stop);
		break;
	}
	case 0xD: {
		octaveShiftType = OctaveShift_Minus_8;
		positions.push_back(OctavePosition_Start);
		positions.push_back(OctavePosition_Stop);
		break;
	}
	case 0xE: {
		octaveShiftType = OctaveShift_15;
		positions.push_back(OctavePosition_Start);
		positions.push_back(OctavePosition_Stop);
		break;
	}
	case 0xF: {
		octaveShiftType = OctaveShift_Minus_15;
		positions.push_back(OctavePosition_Start);
		positions.push_back(OctavePosition_Stop);
		break;
	}
	default:
		break;
	}
}

bool BarsParse::parseOctaveShift(MeasureData* measureData, int /*length*/) {
	Block placeHolder;

	OctaveShift* octave = new OctaveShift();
	measureData->addCrossMeasureElement(octave, true);

	if( !jump(3) ) { return false; }

	// common
	if( !parseCommonBlock(octave) ) { return false; }

	// octave
	if( !readBuffer(placeHolder, 1) ) { return false; }
	unsigned int type = getLowNibble(placeHolder.toUnsignedInt());
	OctaveShiftType octaveShiftType = OctaveShift_8;
	QList<OctaveShiftPosition> positions;
	extractOctave(type, octaveShiftType, positions);

	octave->setOctaveShiftType(octaveShiftType);

	if( !jump(1) ) { return false; }

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	octave->setYOffset(placeHolder.toInt());

	if( !jump(4) ) { return false; }

	// length
	if( !readBuffer(placeHolder, 2) ) { return false; }
	octave->setLength(placeHolder.toUnsignedInt());

	// end tick
	if( !readBuffer(placeHolder, 2) ) { return false; }
	octave->setEndTick(placeHolder.toUnsignedInt());

	// start & stop maybe appear in same measure
	for (int i=0; i<positions.size(); ++i) {
		OctaveShiftPosition position = positions[i];
		OctaveShiftEndPoint* octavePoint = new OctaveShiftEndPoint();
		measureData->addMusicData(octavePoint);

		octavePoint->copyCommonBlock(*octave);
		octavePoint->setOctaveShiftType(octaveShiftType);
		octavePoint->setOctaveShiftPosition(position);
		octavePoint->setEndTick(octave->getEndTick());

		// stop
		if( i==0 && position == OctavePosition_Stop ) {
			octavePoint->start()->setOffset(octave->start()->getOffset()+octave->getLength());
		}

		// end point
		if( i>0 ) {
			octavePoint->start()->setOffset(octave->start()->getOffset()+octave->getLength());
			octavePoint->setTick(octave->getEndTick());
		}
	}

	return true;
}

bool BarsParse::parseMidiController(MeasureData* measureData, int /*length*/) {
	Block placeHolder;
	MidiController* controller = new MidiController();
	measureData->addMidiData(controller);

	parseMidiCommon(controller);

	// value [0, 128)
	if( !readBuffer(placeHolder, 1) ) { return false; }
	controller->setValue(placeHolder.toUnsignedInt());

	// controller number
	if( !readBuffer(placeHolder, 1) ) { return false; }
	controller->setController(placeHolder.toUnsignedInt());

	if( ove_->getIsVersion4() ) {
		if( !jump(2) ) { return false; }
	}

	return true;
}

bool BarsParse::parseMidiProgramChange(MeasureData* measureData, int /*length*/) {
	Block placeHolder;
	MidiProgramChange* program = new MidiProgramChange();
	measureData->addMidiData(program);

	parseMidiCommon(program);

	if( !jump(1) ) { return false; }

	// patch
	if( !readBuffer(placeHolder, 1) ) { return false; }
	program->setPatch(placeHolder.toUnsignedInt());

	if( ove_->getIsVersion4() ) {
		if( !jump(2) ) { return false; }
	}

	return true;
}

bool BarsParse::parseMidiChannelPressure(MeasureData* measureData, int /*length*/) {
	Block placeHolder;
	MidiChannelPressure* pressure = new MidiChannelPressure();
	measureData->addMidiData(pressure);

	parseMidiCommon(pressure);

	if( !jump(1) ) { return false; }

	// pressure
	if( !readBuffer(placeHolder, 1) ) { return false; }
	pressure->setPressure(placeHolder.toUnsignedInt());

	if( ove_->getIsVersion4() )
	{
		if( !jump(2) ) { return false; }
	}

	return true;
}

bool BarsParse::parseMidiPitchWheel(MeasureData* measureData, int /*length*/) {
	Block placeHolder;
	MidiPitchWheel* wheel = new MidiPitchWheel();
	measureData->addMidiData(wheel);

	parseMidiCommon(wheel);

	// pitch wheel
	if( !readBuffer(placeHolder, 2) ) { return false; }
	int value = placeHolder.toUnsignedInt();
	wheel->setValue(value);

	if( ove_->getIsVersion4() ) {
		if( !jump(2) ) { return false; }
	}

	return true;
}

bool BarsParse::parseSizeBlock(int length) {
	if( !jump(length) ) { return false; }

	return true;
}

bool BarsParse::parseMidiCommon(MidiData* ptr) {
	Block placeHolder;

	if( !jump(3) ) { return false; }

	// start position
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->setTick(placeHolder.toUnsignedInt());

	return true;
}

bool BarsParse::parseCommonBlock(MusicData* ptr) {
	Block placeHolder;

	// start tick
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->setTick(placeHolder.toInt());

	// start unit
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->start()->setOffset(placeHolder.toInt());

	if( ove_->getIsVersion4() ) 	{
		// color
		if( !readBuffer(placeHolder, 1) ) { return false; }
		ptr->setColor(placeHolder.toUnsignedInt());

		if( !jump(1) ) { return false; }
	}

	return true;
}

bool BarsParse::parseOffsetCommonBlock(MusicData* ptr) {
	Block placeHolder;

	// offset measure
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->stop()->setMeasure(placeHolder.toUnsignedInt());

	// end unit
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->stop()->setOffset(placeHolder.toInt());

	return true;
}

bool BarsParse::parsePairLinesBlock(PairEnds* ptr) {
	Block placeHolder;

	// left line
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->getLeftLine()->setLine(placeHolder.toInt());

	// right line
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->getRightLine()->setLine(placeHolder.toInt());

	return true;
}

bool BarsParse::parseOffsetElement(OffsetElement* ptr) {
	Block placeHolder;

	// x offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->setXOffset(placeHolder.toInt());

	// y offset
	if( !readBuffer(placeHolder, 2) ) { return false; }
	ptr->setYOffset(placeHolder.toInt());

	return true;
}

bool BarsParse::getCondElementType(unsigned int byteData, CondType& type) {
	if( byteData == 0x09 ) {
		type = Cond_Time_Parameters;
	} else if (byteData == 0x0A) {
		type = Cond_Bar_Number;
	} else if (byteData == 0x16) {
		type = Cond_Decorator;
	} else if (byteData == 0x1C) {
		type = Cond_Tempo;
	} else if (byteData == 0x1D) {
		type = Cond_Text;
	} else if (byteData == 0x25) {
		type = Cond_Expression;
	} else if (byteData == 0x30) {
		type = Cond_Barline_Parameters;
	} else if (byteData == 0x31) {
		type = Cond_Repeat;
	} else if (byteData == 0x32) {
		type = Cond_Numeric_Ending;
	} else {
		return false;
	}

	return true;
}

bool BarsParse::getBdatElementType(unsigned int byteData, BdatType& type) {
	if (byteData == 0x70) {
		type = Bdat_Raw_Note;
	} else if (byteData == 0x80) {
		type = Bdat_Rest;
	} else if (byteData == 0x90) {
		type = Bdat_Note;
	} else if (byteData == 0x10) {
		type = Bdat_Beam;
	} else if (byteData == 0x11) {
		type = Bdat_Harmony;
	} else if (byteData == 0x12) {
		type = Bdat_Clef;
	} else if (byteData == 0x13) {
		type = Bdat_Wedge;
	} else if (byteData == 0x14) {
		type = Bdat_Dynamics;
	} else if (byteData == 0x15) {
		type = Bdat_Glissando;
	} else if (byteData == 0x16) {
		type = Bdat_Decorator;
	} else if (byteData == 0x17) {
		type = Bdat_Key;
	} else if (byteData == 0x18) {
		type = Bdat_Lyric;
	} else if (byteData == 0x19) {
		type = Bdat_Octave_Shift;
	} else if (byteData == 0x1B) {
		type = Bdat_Slur;
	} else if (byteData == 0x1D) {
		type = Bdat_Text;
	} else if (byteData == 0x1E) {
		type = Bdat_Tie;
	} else if (byteData == 0x1F) {
		type = Bdat_Tuplet;
	} else if (byteData == 0x21) {
		type = Bdat_Guitar_Bend;
	} else if (byteData == 0x22) {
		type = Bdat_Guitar_Barre;
	} else if (byteData == 0x23) {
		type = Bdat_Pedal;
	} else if (byteData == 0x24) {
		type = Bdat_KuoHao;
	} else if (byteData == 0x25) {
		type = Bdat_Expressions;
	} else if (byteData == 0x26) {
		type = Bdat_Harp_Pedal;
	} else if (byteData == 0x27) {
		type = Bdat_Multi_Measure_Rest;
	} else if (byteData == 0x28) {
		type = Bdat_Harmony_GuitarFrame;
	} else if (byteData == 0x40) {
		type = Bdat_Graphics_40;
	} else if (byteData == 0x41) {
		type = Bdat_Graphics_RoundRect;
	} else if (byteData == 0x42) {
		type = Bdat_Graphics_Rect;
	} else if (byteData == 0x43) {
		type = Bdat_Graphics_Round;
	} else if (byteData == 0x44) {
		type = Bdat_Graphics_Line;
	} else if (byteData == 0x45) {
		type = Bdat_Graphics_Curve;
	} else if (byteData == 0x46) {
		type = Bdat_Graphics_WedgeSymbol;
	} else if (byteData == 0xAB) {
		type = Bdat_Midi_Controller;
	} else if (byteData == 0xAC) {
		type = Bdat_Midi_Program_Change;
	} else if (byteData == 0xAD) {
		type = Bdat_Midi_Channel_Pressure;
	} else if (byteData == 0xAE) {
		type = Bdat_Midi_Pitch_Wheel;
	} else if (byteData == 0xFF) {
		type = Bdat_Bar_End;
	} else {
		return false;
	}

	return true;
}

///////////////////////////////////////////////////////////////////////////////
LyricChunkParse::LyricChunkParse(OveSong* ove) :
	BasicParse(ove) {
}

void LyricChunkParse::setLyricChunk(SizeChunk* chunk) {
	chunk_ = chunk;
}

// only ove3 has this chunk
bool LyricChunkParse::parse() {
	unsigned int i;
	Block* dataBlock = chunk_->getDataBlock();
	unsigned int blockSize = chunk_->getSizeBlock()->toSize();
	StreamHandle handle(dataBlock->data(), blockSize);
	Block placeHolder;

	handle_ = &handle;

	if( !jump(4) ) { return false; }

	// Lyric count
	if( !readBuffer(placeHolder, 2) ) { return false; }
	unsigned int count = placeHolder.toUnsignedInt();

	for( i=0; i<count; ++i ) {
		LyricInfo info;

		if( !readBuffer(placeHolder, 2) ) { return false; }
		//unsigned int size = placeHolder.toUnsignedInt();

		// 0x0D00
		if( !jump(2) ) { return false; }

		// voice
		if( !readBuffer(placeHolder, 1) ) { return false; }
		info.voice_ = placeHolder.toUnsignedInt();

		// verse
		if( !readBuffer(placeHolder, 1) ) { return false; }
		info.verse_ = placeHolder.toUnsignedInt();

		// track
		if( !readBuffer(placeHolder, 1) ) { return false; }
		info.track_ = placeHolder.toUnsignedInt();

		if( !jump(1) ) { return false; }

		// measure
		if( !readBuffer(placeHolder, 2) ) { return false; }
		info.measure_ = placeHolder.toUnsignedInt();

		// word count
		if( !readBuffer(placeHolder, 2) ) { return false; }
		info.wordCount_ = placeHolder.toUnsignedInt();

		// lyric size
		if( !readBuffer(placeHolder, 2) ) { return false; }
		info.lyricSize_ = placeHolder.toUnsignedInt();

		if( !jump(6) ) { return false; }

		// name
		if( !readBuffer(placeHolder, 32) ) { return false; }
		info.name_ = ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray());

		if( info.lyricSize_ > 0 ) {
			// lyric
			if( info.lyricSize_ > 0 ) {
				if( !readBuffer(placeHolder, info.lyricSize_) ) { return false; }
				info.lyric_ = ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray());
			}

			if( !jump(4) ) { return false; }

			// font
			if( !readBuffer(placeHolder, 2) ) { return false; }
			info.font_ = placeHolder.toUnsignedInt();

			if( !jump(1) ) { return false; }

			// font size
			if( !readBuffer(placeHolder, 1) ) { return false; }
			info.fontSize_ = placeHolder.toUnsignedInt();

			// font style
			if( !readBuffer(placeHolder, 1) ) { return false; }
			info.fontStyle_ = placeHolder.toUnsignedInt();

			if( !jump(1) ) { return false; }

			for( int j=0; j<info.wordCount_; ++j ) {
				if( !jump(8) ) { return false; }
			}
		}

		processLyricInfo(info);
	}

	return true;
}

bool isSpace(char c) {
	return c == ' ' || c == '\n';
}

void LyricChunkParse::processLyricInfo(const LyricInfo& info) {
	int i;
	int j;
	int index = 0; //words

	int measureId = info.measure_-1;
	bool changeMeasure = true;
	MeasureData* measureData = 0;
	int trackMeasureCount = ove_->getTrackBarCount();
	QStringList words = info.lyric_.split(" ", QString::SkipEmptyParts);

	while ( index < words.size() && measureId+1 < trackMeasureCount ) {
		if( changeMeasure ) {
			++measureId;
			measureData = ove_->getMeasureData(info.track_, measureId);
			changeMeasure = false;
		}

		if( measureData == 0 ) { return; }
		QList<NoteContainer*> containers = measureData->getNoteContainers();
		QList<MusicData*> lyrics = measureData->getMusicDatas(MusicData_Lyric);

		for( i=0; i<containers.size() && index<words.size(); ++i ) {
			if( containers[i]->getIsRest() ) {
				continue;
			}

			for( j=0; j<lyrics.size(); ++j ) {
				Lyric* lyric = dynamic_cast<Lyric*>(lyrics[j]);

				if( containers[i]->start()->getOffset() == lyric->start()->getOffset() &&
					(int)containers[i]->getVoice() == info.voice_ &&
					lyric->getVerse() == info.verse_ ) {
						if(index<words.size()) {
							QString l = words[index].trimmed();
							if(!l.isEmpty()) {
								lyric->setLyric(l);
								lyric->setVoice(info.voice_);
							}
						}

					++index;
				}
			}
		}

		changeMeasure = true;
	}
}

///////////////////////////////////////////////////////////////////////////////
TitleChunkParse::TitleChunkParse(OveSong* ove) :
	BasicParse(ove) {
	titleType_ = 0x00000001;
	annotateType_ = 0x00010000;
	writerType_ = 0x00020002;
	copyrightType_ = 0x00030001;
	headerType_ = 0x00040000;
	footerType_ = 0x00050002;
}

void TitleChunkParse::setTitleChunk(SizeChunk* chunk) {
	chunk_ = chunk;
}

QByteArray getByteArray(const Block& block) {
    QByteArray array((char*)block.data(), block.size());
    int index0 = array.indexOf('\0');
    array = array.left(index0);

    return array;
}

bool TitleChunkParse::parse() {
	Block* dataBlock = chunk_->getDataBlock();
	unsigned int blockSize = chunk_->getSizeBlock()->toSize();
	StreamHandle handle(dataBlock->data(), blockSize);
	Block typeBlock;
	unsigned int titleType;

	handle_ = &handle;

	if( !readBuffer(typeBlock, 4) ) { return false; }

	titleType = typeBlock.toUnsignedInt();

	if( titleType == titleType_ || titleType == annotateType_ || titleType == writerType_ || titleType == copyrightType_ ) {
		Block offsetBlock;

		if( !readBuffer(offsetBlock, 4) ) { return false; }

		const unsigned int itemCount = 4;
		unsigned int i;

		for( i=0; i<itemCount; ++i ) {
			if( i>0 ) {
				//0x 00 AB 00 0C 00 00
				if( !jump(6) ) { return false; }
			}

			Block countBlock;
			if( !readBuffer(countBlock, 2) ) { return false; }
			unsigned int titleSize = countBlock.toUnsignedInt();

			Block dataBlock;
			if( !readBuffer(dataBlock, titleSize) ) { return false; }

			QByteArray array = getByteArray(dataBlock);
            if(!array.isEmpty()) {
                addToOve(ove_->getCodecString(array), titleType);
            }
		}

		return true;
	}

	if( titleType == headerType_ || titleType == footerType_ ) {
		if( !jump(10) ) { return false; }

		Block countBlock;
		if( !readBuffer(countBlock, 2) ) { return false; }
		unsigned int titleSize = countBlock.toUnsignedInt();

		Block dataBlock;
		if( !readBuffer(dataBlock, titleSize) ) { return false; }

		QByteArray array = getByteArray(dataBlock);
        addToOve(ove_->getCodecString(array), titleType);

		//0x 00 AB 00 0C 00 00
		if( !jump(6) ) { return false; }

		return true;
	}

	return false;
}

void TitleChunkParse::addToOve(const QString& str, unsigned int titleType) {
	if( str.isEmpty() ) { return; }

	if (titleType == titleType_) {
		ove_->addTitle(str);
	}

	if (titleType == annotateType_) {
		ove_->addAnnotate(str);
	}

	if (titleType == writerType_) {
		ove_->addWriter(str);
	}

	if (titleType == copyrightType_) {
		ove_->addCopyright(str);
	}

	if (titleType == headerType_) {
		ove_->addHeader(str);
	}

	if (titleType == footerType_) {
		ove_->addFooter(str);
	}
}

// OveOrganize.cpp
OveOrganizer::OveOrganizer(OveSong* ove) {
	ove_ = ove;
}

void OveOrganizer::organize() {
	if(ove_ == NULL) {
		return;
	}

	organizeTracks();
	organizeAttributes();
	organizeMeasures();
}

void OveOrganizer::organizeAttributes() {
	int i;
	int j;
	int k;

	// key
	if(ove_->getLineCount() > 0) {
		Line* line = ove_->getLine(0);
		int partBarCount = ove_->getPartBarCount();
		int lastKey = 0;

		if(line != 0){
			for(i=0; i<line->getStaffCount(); ++i) {
				QPair<int, int> partStaff = ove_->trackToPartStaff(i);
				Staff* staff = line->getStaff(i);
				lastKey = staff->getKeyType();

				for(j=0; j<partBarCount; ++j) {
					MeasureData* measureData = ove_->getMeasureData(partStaff.first, partStaff.second, j);

					if(measureData != 0) {
						Key* key = measureData->getKey();

						if( j==0 ) {
							key->setKey(lastKey);
							key->setPreviousKey(lastKey);
						}

						if( !key->getSetKey() ) {
							key->setKey(lastKey);
							key->setPreviousKey(lastKey);
						}
						else {
							if( key->getKey() != lastKey ) {
								lastKey = key->getKey();
							}
						}
					}
				}
			}
		}
	}

	// clef
	if( ove_->getLineCount() > 0 ) {
		Line* line = ove_->getLine(0);
		int partBarCount = ove_->getPartBarCount();
		ClefType lastClefType = Clef_Treble;

		if(line != 0){
			for( i=0; i<line->getStaffCount(); ++i ) {
				QPair<int, int> partStaff = ove_->trackToPartStaff(i);
				Staff* staff = line->getStaff(i);
				lastClefType = staff->getClefType();

				for( j=0; j<partBarCount; ++j )	{
					MeasureData* measureData = ove_->getMeasureData(partStaff.first, partStaff.second, j);

					if(measureData != 0) {
						Clef* clefPtr = measureData->getClef();
						clefPtr->setClefType((int)lastClefType);

						const QList<MusicData*>& clefs = measureData->getMusicDatas(MusicData_Clef);

						for( k=0; k<clefs.size(); ++k ) {
							Clef* clef = dynamic_cast<Clef*>(clefs[k]);
							lastClefType = clef->getClefType();
						}
					}
				}
			}
		}
	}
}

Staff* getStaff(OveSong* ove, int track) {
	if (ove->getLineCount() > 0) {
		Line* line = ove->getLine(0);
		if(line != 0 && line->getStaffCount() > 0) {
			Staff* staff = line->getStaff(track);
			return staff;
		}
	}

	return 0;
}

void OveOrganizer::organizeTracks() {
	int i;
	//QList<QPair<ClefType, int> > trackChannels;
	QList<Track*> tracks = ove_->getTracks();
	QList<bool> comboStaveStarts;

	for( i=0; i<tracks.size(); ++i ) {
		comboStaveStarts.push_back(false);
	}

	for( i=0; i<tracks.size(); ++i ) {
		Staff* staff = getStaff(ove_, i);
		if(staff != 0) {
			if(staff->getGroupType() == Group_Brace && staff->getGroupStaffCount() == 1 ) {
				comboStaveStarts[i] = true;
			}
		}

		/*if( i < tracks.size() - 1 ) {
			if( tracks[i]->getStartClef() == Clef_Treble &&
				tracks[i+1]->getStartClef() == Clef_Bass &&
				tracks[i]->getChannel() == tracks[i+1]->get_channel() ) {
			}
		}*/
	}

	int trackId = 0;
	QList<int> partStaffCounts;

	while( trackId < (int)tracks.size() ) {
		int partTrackCount = 1;

		if( comboStaveStarts[trackId] ) {
			partTrackCount = 2;
		}

		partStaffCounts.push_back(partTrackCount);
		trackId += partTrackCount;
	}

	ove_->setPartStaffCounts(partStaffCounts);
}

void OveOrganizer::organizeMeasures() {
	int trackBarCount = ove_->getTrackBarCount();

	for( int i=0; i<ove_->getPartCount(); ++i ) {
		int partStaffCount = ove_->getStaffCount(i);

		for( int j=0; j<partStaffCount; ++j ) {
			for( int k=0; k<trackBarCount; ++k ) {
				Measure* measure = ove_->getMeasure(k);
				MeasureData* measureData = ove_->getMeasureData(i, j, k);

				organizeMeasure(i, j, measure, measureData);
			}
		}
	}
}

void OveOrganizer::organizeMeasure(int part, int track, Measure* measure, MeasureData* measureData) {
	// note containers
	organizeContainers(part, track, measure, measureData);

	// single end data
	organizeMusicDatas(part, track, measure, measureData);

	// cross measure elements
	organizeCrossMeasureElements(part, track, measure, measureData);
}

void addToList(QList<int>& list, int number) {
	for(int i=0; i<list.size(); ++i){
		if(list[i] == number){
			return;
		}
	}

	list.push_back(number);
}

void OveOrganizer::organizeContainers(int /*part*/, int /*track*/,
        Measure* measure, MeasureData* measureData) {
	int i;
	QList<NoteContainer*> containers = measureData->getNoteContainers();
	int barUnits = measure->getTime()->getUnits();
	QList<int> voices;

	for(i=0; i<containers.size(); ++i){
		int endUnit = barUnits;
		if( i < containers.size() - 1 ) {
			endUnit = containers[i+1]->start()->getOffset();
		}

		containers[i]->stop()->setOffset(endUnit);
		addToList(voices, containers[i]->getVoice());
	}

	// shift voices
	qSort(voices.begin(), voices.end());

	for (i = 0; i < voices.size(); ++i) {
		int voice = voices[i];
		// voice -> i
		for(int j=0; j<(int)containers.size(); ++j) {
		    int avoice = containers[j]->getVoice();
			if ( avoice == voice && avoice != i ) {
				containers[j]->setVoice(i);
			}
		}
	}
}

void OveOrganizer::organizeMusicDatas(int /*part*/, int /*track*/, Measure* measure, MeasureData* measureData) {
	int i;
	int barIndex = measure->getBarNumber()->getIndex();
	QList<MusicData*> datas = measureData->getMusicDatas(MusicData_None);

	for(i=0; i<datas.size(); ++i) {
		datas[i]->start()->setMeasure(barIndex);
	}
}

void OveOrganizer::organizeCrossMeasureElements(int part, int track, Measure* measure, MeasureData* measureData) {
	int i;
	QList<MusicData*> pairs = measureData->getCrossMeasureElements(MusicData_None, MeasureData::PairType_Start);

	for(i=0; i<pairs.size(); ++i) {
		MusicData* pair = pairs[i];

		switch ( pair->getMusicDataType() ) {
		case MusicData_Beam :
		case MusicData_Glissando :
		case MusicData_Slur :
		case MusicData_Tie :
		case MusicData_Tuplet :
		case MusicData_Pedal :
		case MusicData_Numeric_Ending :
		//case MusicData_OctaveShift_EndPoint :
		case MusicData_Measure_Repeat :	{
				organizePairElement(pair, part, track, measure, measureData);
				break;
			}
		case MusicData_OctaveShift : {
				OctaveShift* octave = dynamic_cast<OctaveShift*>(pair);
				organizeOctaveShift(octave, measure, measureData);
				break;
			}
		case MusicData_Wedge : {
				Wedge* wedge = dynamic_cast<Wedge*>(pair);
				organizeWedge(wedge, part, track, measure, measureData);
				break;
			}
		default:
			break;
		}
	}
}

void OveOrganizer::organizePairElement(
						MusicData* data,
						int part,
						int track,
						Measure* measure,
						MeasureData* measureData) {
	int bar1Index = measure->getBarNumber()->getIndex();
	int bar2Index = bar1Index + data->stop()->getMeasure();
	MeasureData* measureData2 = ove_->getMeasureData(part, track, bar2Index);

	data->start()->setMeasure(bar1Index);

	if(measureData2 != 0 && measureData != measureData2) {
		measureData2->addCrossMeasureElement(data, false);
	}

	if( data->getMusicDataType() == MusicData_Tuplet ){
		Tuplet* tuplet = dynamic_cast<Tuplet*>(data);
		const QList<NoteContainer*> containers = measureData->getNoteContainers();

		for(int i=0; i<containers.size(); ++i){
			if(containers[i]->getTick() > tuplet->getTick()){
				break;
			}

			if(containers[i]->getTick() == tuplet->getTick()){
				tuplet->setNoteType(containers[i]->getNoteType());
			}
		}

		int tupletTick = NoteUtility::NoteTypeToTick(tuplet->getNoteType(), ove_->getQuarter())*tuplet->getSpace();
		if( tuplet->getTick() % tupletTick != 0 ) {
			int newStartTick = (tuplet->getTick() / tupletTick) * tupletTick;

			for(int i=0; i<containers.size(); ++i){
				if( containers[i]->getTick() == newStartTick &&
					containers[i]->getTuplet() == tuplet->getTuplet()) {
					tuplet->setTick(containers[i]->getTick());
					tuplet->start()->setOffset(containers[i]->start()->getOffset());
				}
			}
		}
	}
}

void OveOrganizer::organizeOctaveShift(
						OctaveShift* octave,
						Measure* measure,
						MeasureData* measureData) {
	// octave shift
	int i;
	const QList<NoteContainer*> containers = measureData->getNoteContainers();
	int barIndex = measure->getBarNumber()->getIndex();

	octave->start()->setMeasure(barIndex);

	for(i=0; i<containers.size(); ++i) {
		int noteShift = octave->getNoteShift();
		int containerTick = containers[i]->getTick();

		if( octave->getTick() <= containerTick && octave->getEndTick() > containerTick )	{
			containers[i]->setNoteShift(noteShift);
		}
	}
}

bool getMiddleUnit(
			OveSong* ove, int /*part*/, int /*track*/,
			Measure* measure1, Measure* measure2, int unit1, int /*unit2*/,
			Measure* middleMeasure, int& middleUnit) {
	QList<int> barUnits;
	int i;
	int bar1Index = measure1->getBarNumber()->getIndex();
	int bar2Index = measure2->getBarNumber()->getIndex();
	int sumUnit = 0;

	for( int j=bar1Index; j<=bar2Index; ++j ) {
		Measure* measure = ove->getMeasure(j);
		barUnits.push_back(measure->getTime()->getUnits());
		sumUnit += measure->getTime()->getUnits();
	}

	int currentSumUnit = 0;
	for( i=0; i<barUnits.size(); ++i ) {
		int barUnit = barUnits[i];

		if( i==0 ) {
			barUnit = barUnits[i] - unit1;
		}

		if( currentSumUnit + barUnit < sumUnit/2 ) {
			currentSumUnit += barUnit;
		}
		else {
			break;
		}
	}

	if( i < barUnits.size() ) {
		int barMiddleIndex = bar1Index + i;
		middleMeasure = ove->getMeasure(barMiddleIndex);
		middleUnit = sumUnit/2 - currentSumUnit;

		return true;
	}

	return false;
}

void OveOrganizer::organizeWedge(Wedge* wedge, int part, int track, Measure* measure, MeasureData* measureData) {
	int bar1Index = measure->getBarNumber()->getIndex();
	int bar2Index = bar1Index + wedge->stop()->getMeasure();
	MeasureData* measureData2 = ove_->getMeasureData(part, track, bar2Index);
	WedgeType wedgeType = wedge->getWedgeType();

	if( wedge->getWedgeType() == Wedge_Double_Line ) {
		wedgeType = Wedge_Cres_Line;
	}

	wedge->start()->setMeasure(bar1Index);

	WedgeEndPoint* startPoint = new WedgeEndPoint();
	measureData->addMusicData(startPoint);

	startPoint->setTick(wedge->getTick());
	startPoint->start()->setOffset(wedge->start()->getOffset());
	startPoint->setWedgeStart(true);
	startPoint->setWedgeType(wedgeType);
	startPoint->setHeight(wedge->getHeight());

	WedgeEndPoint* stopPoint = new WedgeEndPoint();

	stopPoint->setTick(wedge->getTick());
	stopPoint->start()->setOffset(wedge->stop()->getOffset());
	stopPoint->setWedgeStart(false);
	stopPoint->setWedgeType(wedgeType);
	stopPoint->setHeight(wedge->getHeight());

	if(measureData2 != 0) {
		measureData2->addMusicData(stopPoint);
	}

	if( wedge->getWedgeType() == Wedge_Double_Line ) {
		Measure* middleMeasure = NULL;
		int middleUnit = 0;

		getMiddleUnit(
			ove_, part, track,
			measure, ove_->getMeasure(bar2Index),
			wedge->start()->getOffset(), wedge->stop()->getOffset(),
			middleMeasure, middleUnit);

		if( middleMeasure != 0 ) {
			WedgeEndPoint* midStopPoint = new WedgeEndPoint();
			measureData->addMusicData(midStopPoint);

			midStopPoint->setTick(wedge->getTick());
			midStopPoint->start()->setOffset(middleUnit);
			midStopPoint->setWedgeStart(false);
			midStopPoint->setWedgeType(Wedge_Cres_Line);
			midStopPoint->setHeight(wedge->getHeight());

			WedgeEndPoint* midStartPoint = new WedgeEndPoint();
			measureData->addMusicData(midStartPoint);

			midStartPoint->setTick(wedge->getTick());
			midStartPoint->start()->setOffset(middleUnit);
			midStartPoint->setWedgeStart(true);
			midStartPoint->setWedgeType(Wedge_Decresc_Line);
			midStartPoint->setHeight(wedge->getHeight());
		}
	}
}


// OveSerialize.cpp
enum ChunkType {
	Chunk_OVSC = 00 ,
	Chunk_TRKL,
	Chunk_TRAK,
	Chunk_PAGL,
	Chunk_PAGE,
	Chunk_LINL,
	Chunk_LINE,
	Chunk_STAF,
	Chunk_BARL,
	Chunk_MEAS,
	Chunk_COND,
	Chunk_BDAT,
	Chunk_PACH,
	Chunk_FNTS,
	Chunk_ODEV,
	Chunk_TITL,
	Chunk_ALOT,
	Chunk_ENGR,
	Chunk_FMAP,
	Chunk_PCPR,

	// Overture 3.6
	Chunk_LYRC,

	Chunk_NONE
};

ChunkType nameToChunkType(const NameBlock& name) {
	ChunkType type = Chunk_NONE;

	if (name.isEqual("OVSC")) {
		type = Chunk_OVSC;
	} else if (name.isEqual("TRKL")) {
		type = Chunk_TRKL;
	} else if (name.isEqual("TRAK")) {
		type = Chunk_TRAK;
	} else if (name.isEqual("PAGL")) {
		type = Chunk_PAGL;
	} else if (name.isEqual("PAGE")) {
		type = Chunk_PAGE;
	} else if (name.isEqual("LINL")) {
		type = Chunk_LINL;
	} else if (name.isEqual("LINE")) {
		type = Chunk_LINE;
	} else if (name.isEqual("STAF")) {
		type = Chunk_STAF;
	} else if (name.isEqual("BARL")) {
		type = Chunk_BARL;
	} else if (name.isEqual("MEAS")) {
		type = Chunk_MEAS;
	} else if (name.isEqual("COND")) {
		type = Chunk_COND;
	} else if (name.isEqual("BDAT")) {
		type = Chunk_BDAT;
	} else if (name.isEqual("PACH")) {
		type = Chunk_PACH;
	} else if (name.isEqual("FNTS")) {
		type = Chunk_FNTS;
	} else if (name.isEqual("ODEV")) {
		type = Chunk_ODEV;
	} else if (name.isEqual("TITL")) {
		type = Chunk_TITL;
	} else if (name.isEqual("ALOT")) {
		type = Chunk_ALOT;
	} else if (name.isEqual("ENGR")) {
		type = Chunk_ENGR;
	} else if (name.isEqual("FMAP")) {
		type = Chunk_FMAP;
	} else if (name.isEqual("PCPR")) {
		type = Chunk_PCPR;
	} else if (name.isEqual("LYRC")) {
		type = Chunk_LYRC;
	}

	return type;
}

int chunkTypeToMaxTimes(ChunkType type) {
	int maxTimes = -1; // no limit

	switch (type) {
	case Chunk_OVSC: {
		maxTimes = 1;
		break;
	}
	case Chunk_TRKL: {//	case Chunk_TRAK :
		maxTimes = 1;
		break;
	}
	case Chunk_PAGL: {//	case Chunk_PAGE :
		maxTimes = 1;
		break;
	}
//	case Chunk_LINE :
//	case Chunk_STAF :
	case Chunk_LINL: {
		maxTimes = 1;
		break;
	}
//	case Chunk_MEAS :
//	case Chunk_COND :
//	case Chunk_BDAT :
	case Chunk_BARL: {
		maxTimes = 1;
		break;
	}
	case Chunk_PACH:
	case Chunk_FNTS:
	case Chunk_ODEV:
	case Chunk_ALOT:
	case Chunk_ENGR:
	case Chunk_FMAP:
	case Chunk_PCPR: {
		maxTimes = 1;
		break;
	}
	case Chunk_TITL: {
		maxTimes = 8;
		break;
	}
	case Chunk_LYRC: {
		maxTimes = 1;
		break;
	}
//	case Chunk_NONE :
	default:
		break;
	}

	return maxTimes;
}

///////////////////////////////////////////////////////////////////////////////////////////

OveSerialize::OveSerialize() :
	ove_(0),
	streamHandle_(0),
	notify_(0) {
}

OveSerialize::~OveSerialize() {
	if(streamHandle_ != 0) {
		delete streamHandle_;
		streamHandle_ = 0;
	}
}

void OveSerialize::setOve(OveSong* ove) {
	ove_ = ove;
}

void OveSerialize::setFileStream(unsigned char* buffer, unsigned int size) {
	streamHandle_ = new StreamHandle(buffer, size);
}

void OveSerialize::setNotify(IOveNotify* notify) {
	notify_ = notify;
}

void OveSerialize::messageOutError() {
	if (notify_ != NULL) {
		notify_->loadError();
	}
}

void OveSerialize::messageOut(const QString& str) {
	if (notify_ != NULL) {
		notify_->loadInfo(str);
	}
}

bool OveSerialize::load(void) {
	if(streamHandle_ == 0)
		return false;

	if( !readHeader() ) {
		messageOutError();
		return false;
	}

	unsigned int i;
	QMap<ChunkType, int> chunkTimes;
	//bool firstEnter = true;

	for( i=(int)Chunk_OVSC; i<(int)Chunk_NONE; ++i ) {
		chunkTimes[(ChunkType)i] = 0;
	}

	ChunkType chunkType = Chunk_NONE;

	do {
		NameBlock nameBlock;
		SizeChunk sizeChunk;

		if( !readNameBlock(nameBlock) ) { return false; }

		chunkType = nameToChunkType(nameBlock);
		++chunkTimes[chunkType];
		int maxTime = chunkTypeToMaxTimes(chunkType);

		if( maxTime > 0 && chunkTimes[chunkType] > maxTime ) {
			messageOut("format not support, chunk appear more than accept.\n");
			return false;
		}

		switch (chunkType) {
		/*case Chunk_OVSC :
		 {
		 if( !readHeadData(&sizeChunk) )
		 {
		 messageOut_error();
		 return false;
		 }

		 break;
		 }*/
		case Chunk_TRKL: {
			if (!readTracksData()) {
				messageOutError();
				return false;
			}

			break;
		}
		case Chunk_PAGL: {
			if (!readPagesData()) {
				messageOutError();
				return false;
			}

			break;
		}
		case Chunk_LINL: {
			if (!readLinesData()) {
				messageOutError();
				return false;
			}

			break;
		}
		case Chunk_BARL: {
			if (!readBarsData()) {
				messageOutError();
				return false;
			}

			break;
		}
		case Chunk_TRAK:
		case Chunk_PAGE:
		case Chunk_LINE:
		case Chunk_STAF:
		case Chunk_MEAS:
		case Chunk_COND:
		case Chunk_BDAT: {
			return false;
			break;
		}
		case Chunk_LYRC: {
			SizeChunk lyricChunk;
			if (!readSizeChunk(&lyricChunk)) {
				messageOutError();
				return false;
			}

			LyricChunkParse parse(ove_);

			parse.setLyricChunk(&lyricChunk);
			parse.parse();

			break;
		}
		case Chunk_TITL: {
			SizeChunk titleChunk;
			if (!readSizeChunk(&titleChunk)) {
				messageOutError();
				return false;
			}

			TitleChunkParse titleChunkParse(ove_);

			titleChunkParse.setTitleChunk(&titleChunk);
			titleChunkParse.parse();

			break;
		}
		case Chunk_PACH:
		case Chunk_FNTS:
		case Chunk_ODEV:
		case Chunk_ALOT:
		case Chunk_ENGR:
		case Chunk_FMAP:
		case Chunk_PCPR: {
			if (!readSizeChunk(&sizeChunk)) {
				messageOutError();
				return false;
			}

			break;
		}
		default:
			/*if( firstEnter )
			 {
			 QString info = "Not compatible file, try to load and save with newer version, Overture 4 is recommended.\n";
			 messageOut(info);
			 messageOutError();

			 return false;
			 }*/

			break;
		}

		//firstEnter = false;
    } while ( chunkType != Chunk_NONE );

//	if( !readOveEnd() ) { return false; }

	// organize OveData
	OVE::OveOrganizer organizer(ove_);
	organizer.organize();

	return true;
}

void OveSerialize::release() {
	delete this;
}

bool OveSerialize::readHeader() {
	ChunkType chunkType = Chunk_NONE;
	NameBlock nameBlock;
	SizeChunk sizeChunk;

	if (!readNameBlock(nameBlock)) {
		return false;
	}

	chunkType = nameToChunkType(nameBlock);
	//int maxTime = chunkTypeToMaxTimes(chunkType);

	if (chunkType == Chunk_OVSC) {
		if (readHeadData(&sizeChunk)) {
			return true;
		}
	}

	QString info = "Not compatible file, try to load and save with newer version, Overture 4 is recommended.\n";
	messageOut(info);

	return false;
}

bool OveSerialize::readHeadData(SizeChunk* ovscChunk) {
	if (!readSizeChunk(ovscChunk))
		return false;

	OvscParse ovscParse(ove_);

	ovscParse.setNotify(notify_);
	ovscParse.setOvsc(ovscChunk);

	return ovscParse.parse();
}

bool OveSerialize::readTracksData() {
	GroupChunk trackGroupChunk;

	if (!readGroupChunk(&trackGroupChunk))
		return false;

	unsigned int i;
	unsigned short trackCount = trackGroupChunk.getCountBlock()->toCount();

	for (i = 0; i < trackCount; ++i) {
		SizeChunk* trackChunk = new SizeChunk();

		if (ove_->getIsVersion4()) {
			if (!readChunkName(trackChunk, Chunk::TrackName)) {
				return false;
			}
			if (!readSizeChunk(trackChunk)) {
				return false;
			}
		} else {
			if (!readDataChunk(trackChunk->getDataBlock(),
					SizeChunk::version3TrackSize)) {
				return false;
			}
		}

		TrackParse trackParse(ove_);

		trackParse.setTrack(trackChunk);
		trackParse.parse();
	}

	return true;
}

bool OveSerialize::readPagesData() {
	GroupChunk pageGroupChunk;

	if (!readGroupChunk(&pageGroupChunk))
		return false;

	unsigned short pageCount = pageGroupChunk.getCountBlock()->toCount();
	unsigned int i;
	PageGroupParse parse(ove_);

	for (i = 0; i < pageCount; ++i) {
		SizeChunk* pageChunk = new SizeChunk();

		if (!readChunkName(pageChunk, Chunk::PageName)) {
			return false;
		}
		if (!readSizeChunk(pageChunk)) {
			return false;
		}

		parse.addPage(pageChunk);
	}

	if (!parse.parse()) {
		return false;
	}

	return true;
}

bool OveSerialize::readLinesData() {
	GroupChunk lineGroupChunk;
	if (!readGroupChunk(&lineGroupChunk))
		return false;

	unsigned short lineCount = lineGroupChunk.getCountBlock()->toCount();
	int i;
	unsigned int j;
	QList<SizeChunk*> lineChunks;
	QList<SizeChunk*> staffChunks;

	for (i = 0; i < lineCount; ++i) {
		SizeChunk* lineChunk = new SizeChunk();

		if (!readChunkName(lineChunk, Chunk::LineName)) {
			return false;
		}
		if (!readSizeChunk(lineChunk)) {
			return false;
		}

		lineChunks.push_back(lineChunk);

		StaffCountGetter getter(ove_);
		unsigned int staffCount = getter.getStaffCount(lineChunk);

		for (j = 0; j < staffCount; ++j) {
			SizeChunk* staffChunk = new SizeChunk();

			if (!readChunkName(staffChunk, Chunk::StaffName)) {
				return false;
			}
			if (!readSizeChunk(staffChunk)) {
				return false;
			}

			staffChunks.push_back(staffChunk);
		}
	}

	LineGroupParse parse(ove_);

	parse.setLineGroup(&lineGroupChunk);

	for (i = 0; i < lineChunks.size(); ++i) {
		parse.addLine(lineChunks[i]);
	}

	for (i = 0; i < staffChunks.size(); ++i) {
		parse.addStaff(staffChunks[i]);
	}

	if (!parse.parse()) {
		return false;
	}

	return true;
}

bool OveSerialize::readBarsData() {
	GroupChunk barGroupChunk;
	if (!readGroupChunk(&barGroupChunk))
		return false;

	unsigned short measCount = barGroupChunk.getCountBlock()->toCount();
	int i;

	QList<SizeChunk*> measureChunks;
	QList<SizeChunk*> conductChunks;
	QList<SizeChunk*> bdatChunks;

	ove_->setTrackBarCount(measCount);

	// read chunks
	for (i = 0; i < measCount; ++i) {
		SizeChunk* measureChunkPtr = new SizeChunk();

		if (!readChunkName(measureChunkPtr, Chunk::MeasureName)) {
			return false;
		}
		if (!readSizeChunk(measureChunkPtr)) {
			return false;
		}

		measureChunks.push_back(measureChunkPtr);
	}

	for (i = 0; i < measCount; ++i) {
		SizeChunk* conductChunkPtr = new SizeChunk();

		if (!readChunkName(conductChunkPtr, Chunk::ConductName))
			return false;

		if (!readSizeChunk(conductChunkPtr))
			return false;

		conductChunks.push_back(conductChunkPtr);
	}

	int bdatCount = ove_->getTrackCount() * measCount;
	for (i = 0; i < bdatCount; ++i) {
		SizeChunk* batChunkPtr = new SizeChunk();

		if (!readChunkName(batChunkPtr, Chunk::BdatName)) {
			return false;
		}
		if (!readSizeChunk(batChunkPtr)) {
			return false;
		}

		bdatChunks.push_back(batChunkPtr);
	}

	// parse bars
	BarsParse barsParse(ove_);

	for (i = 0; i < (int) measureChunks.size(); ++i) {
		barsParse.addMeasure(measureChunks[i]);
	}

	for (i = 0; i < (int) conductChunks.size(); ++i) {
		barsParse.addConduct(conductChunks[i]);
	}

	for (i = 0; i < (int) bdatChunks.size(); ++i) {
		barsParse.addBdat(bdatChunks[i]);
	}

	barsParse.setNotify(notify_);
	if (!barsParse.parse()) {
		return false;
	}

	return true;
}

bool OveSerialize::readOveEnd() {
	if (streamHandle_ == 0)
		return false;

	const unsigned int END_OVE1 = 0xffffffff;
	const unsigned int END_OVE2 = 0x00000000;
	unsigned int buffer;

	if (!streamHandle_->read((char*) &buffer, sizeof(unsigned int)))
		return false;

	if (buffer != END_OVE1)
		return false;

	if (!streamHandle_->read((char*) &buffer, sizeof(unsigned int)))
		return false;

	if (buffer != END_OVE2)
		return false;

	return true;
}

/////////////////////////////////////////////////////////////////////////////////////////
bool OveSerialize::readNameBlock(NameBlock& nameBlock) {
	if (streamHandle_ == 0)
		return false;

	if (!streamHandle_->read((char*) nameBlock.data(), nameBlock.size()))
		return false;

	return true;
}

bool OveSerialize::readChunkName(Chunk* /*chunk*/, const QString& name) {
	if (streamHandle_ == 0)
		return false;

	NameBlock nameBlock;

	if (!streamHandle_->read((char*) nameBlock.data(), nameBlock.size()))
		return false;

	if (!(nameBlock.toStrByteArray() == name))
		return false;

	return true;
}

bool OveSerialize::readSizeChunk(SizeChunk* sizeChunk) {
	if (streamHandle_ == 0)
		return false;

	SizeBlock* sizeBlock = sizeChunk->getSizeBlock();

	if (!streamHandle_->read((char*) sizeBlock->data(), sizeBlock->size()))
		return false;

	unsigned int blockSize = sizeBlock->toSize();

	sizeChunk->getDataBlock()->resize(blockSize);

	Block* dataBlock = sizeChunk->getDataBlock();

	if (!streamHandle_->read((char*) dataBlock->data(), blockSize))
		return false;

	return true;
}

bool OveSerialize::readDataChunk(Block* block, unsigned int size) {
	if (streamHandle_ == 0)
		return false;

	block->resize(size);

	if (!streamHandle_->read((char*) block->data(), size))
		return false;

	return true;
}

bool OveSerialize::readGroupChunk(GroupChunk* groupChunk) {
	if (streamHandle_ == 0)
		return false;

	CountBlock* countBlock = groupChunk->getCountBlock();

	if (!streamHandle_->read((char*) countBlock->data(), countBlock->size()))
		return false;

	return true;
}

IOVEStreamLoader* createOveStreamLoader() {
	return new OveSerialize;
}

}
